mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-06 14:09:58 +00:00
Another intent on load store op none impl
This commit is contained in:
@@ -136,6 +136,37 @@ RenderingFormats PipelineFormats(const FixedPipelineState& state, const Device&
|
||||
return MakeRenderingFormats(device, color_formats, depth_format);
|
||||
}
|
||||
|
||||
struct AttachmentAccess {
|
||||
u32 touched;
|
||||
u32 written;
|
||||
};
|
||||
|
||||
AttachmentAccess MakeAttachmentAccess(const Maxwell& regs) {
|
||||
AttachmentAccess access{};
|
||||
for (size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
|
||||
size_t mask_index = index;
|
||||
if (regs.color_mask_common) {
|
||||
mask_index = 0;
|
||||
}
|
||||
const auto& mask = regs.color_mask[mask_index];
|
||||
if (mask.R || mask.G || mask.B || mask.A) {
|
||||
access.touched |= 1u << index;
|
||||
access.written |= 1u << index;
|
||||
}
|
||||
}
|
||||
if (regs.depth_test_enable || regs.depth_bounds_enable) {
|
||||
access.touched |= Scheduler::DEPTH_ATTACHMENT_BIT;
|
||||
}
|
||||
if (regs.depth_test_enable && regs.depth_write_enabled) {
|
||||
access.written |= Scheduler::DEPTH_ATTACHMENT_BIT;
|
||||
}
|
||||
if (regs.stencil_enable) {
|
||||
access.touched |= Scheduler::STENCIL_ATTACHMENT_BIT;
|
||||
access.written |= Scheduler::STENCIL_ATTACHMENT_BIT;
|
||||
}
|
||||
return access;
|
||||
}
|
||||
|
||||
size_t NumAttachments(const FixedPipelineState& state) {
|
||||
size_t num{};
|
||||
for (size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
|
||||
@@ -586,7 +617,8 @@ bool GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
||||
if (buffer_cache.TakeDrawHazard()) {
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
}
|
||||
scheduler.RequestRenderpass(texture_cache.GetFramebuffer());
|
||||
const AttachmentAccess access = MakeAttachmentAccess(maxwell3d->regs);
|
||||
scheduler.RequestRenderpass(texture_cache.GetFramebuffer(), access.touched, access.written);
|
||||
buffer_cache.CommitDrawWrites();
|
||||
if (!is_built.load(std::memory_order::relaxed)) {
|
||||
// Wait for the pipeline to be built
|
||||
|
||||
@@ -263,8 +263,6 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, bool skip_empty, Func&& draw
|
||||
pipeline->SetEngine(maxwell3d, gpu_memory);
|
||||
if (!pipeline->Configure(is_indexed))
|
||||
return;
|
||||
scheduler.MarkDepthWrites(maxwell3d->regs.depth_test_enable != 0 &&
|
||||
maxwell3d->regs.depth_write_enabled != 0);
|
||||
|
||||
UpdateDynamicStates(pipeline->HasDynamicVertexInput());
|
||||
|
||||
@@ -584,7 +582,6 @@ void RasterizerVulkan::Clear(u32 layer_count) {
|
||||
if (aspect_flags == 0) {
|
||||
return;
|
||||
}
|
||||
scheduler.MarkDepthWrites(!can_defer_clear && (aspect_flags & VK_IMAGE_ASPECT_DEPTH_BIT) != 0);
|
||||
|
||||
if (use_stencil && framebuffer->HasAspectStencilBit() && regs.stencil_front_mask != 0xFF &&
|
||||
regs.stencil_front_mask != 0) {
|
||||
|
||||
@@ -27,6 +27,15 @@
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
|
||||
namespace Vulkan {
|
||||
namespace {
|
||||
struct BeginRenderingCommand {
|
||||
void operator()(vk::CommandBuffer cmdbuf, vk::CommandBuffer) const {
|
||||
BeginRendering(cmdbuf, attachments);
|
||||
}
|
||||
|
||||
RenderingAttachments attachments;
|
||||
};
|
||||
} // Anonymous namespace
|
||||
|
||||
void Scheduler::CommandChunk::ExecuteAll(vk::CommandBuffer cmdbuf,
|
||||
vk::CommandBuffer upload_cmdbuf) {
|
||||
@@ -104,6 +113,7 @@ void Scheduler::DispatchWork() {
|
||||
work_queue.push(std::move(chunk));
|
||||
}
|
||||
event_cv.notify_all();
|
||||
recorded_attachments = nullptr;
|
||||
AcquireNewChunk();
|
||||
}
|
||||
}
|
||||
@@ -113,7 +123,8 @@ void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer,
|
||||
PublishComputeWrites();
|
||||
state.framebuffer_id = framebuffer->Id();
|
||||
++renderpass_serial;
|
||||
renderpass_depth_writes = false;
|
||||
attachments_touched = 0;
|
||||
attachments_written = 0;
|
||||
|
||||
if (GPU::Logging::IsActive() && Settings::values.gpu_log_vulkan_calls.GetValue()) {
|
||||
const VkExtent2D render_area = attachments.render_area.extent;
|
||||
@@ -123,7 +134,13 @@ void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer,
|
||||
GPU::Logging::GPULogger::GetInstance().LogRenderPassBegin(render_pass_info);
|
||||
}
|
||||
|
||||
Record([attachments](vk::CommandBuffer cmdbuf) { BeginRendering(cmdbuf, attachments); });
|
||||
BeginRenderingCommand command{attachments};
|
||||
BeginRenderingCommand* recorded = chunk->Record(command);
|
||||
if (recorded == nullptr) {
|
||||
DispatchWork();
|
||||
recorded = chunk->Record(command);
|
||||
}
|
||||
recorded_attachments = &recorded->attachments;
|
||||
num_renderpass_images = framebuffer->NumImages();
|
||||
renderpass_images = framebuffer->Images();
|
||||
renderpass_image_ranges = framebuffer->ImageRanges();
|
||||
@@ -161,7 +178,9 @@ void Scheduler::RealizeDeferredClear() {
|
||||
}
|
||||
EndRenderPass();
|
||||
BeginRenderPassImpl(dc.framebuffer, attachments);
|
||||
renderpass_depth_writes = dc.depth_stencil;
|
||||
if (dc.depth_stencil) {
|
||||
attachments_written |= DEPTH_ATTACHMENT_BIT | STENCIL_ATTACHMENT_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
bool Scheduler::DeferColorClear(const Framebuffer* framebuffer, u32 rt_slot,
|
||||
@@ -201,17 +220,16 @@ void Scheduler::FlushDeferredClear() {
|
||||
EndRenderPass();
|
||||
}
|
||||
|
||||
void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
||||
void Scheduler::RequestRenderpass(const Framebuffer* framebuffer, u32 touched, u32 written) {
|
||||
if (deferred_clear.framebuffer == framebuffer) {
|
||||
RealizeDeferredClear();
|
||||
return;
|
||||
} else if (framebuffer->Id() != state.framebuffer_id) {
|
||||
// Ends any active pass and realizes a deferred clear
|
||||
EndRenderPass();
|
||||
BeginRenderPassImpl(framebuffer, framebuffer->Attachments());
|
||||
}
|
||||
if (framebuffer->Id() == state.framebuffer_id) {
|
||||
return;
|
||||
}
|
||||
// Ends any active pass and realizes a deferred clear
|
||||
EndRenderPass();
|
||||
BeginRenderPassImpl(framebuffer, framebuffer->Attachments());
|
||||
attachments_touched |= touched;
|
||||
attachments_written |= written;
|
||||
}
|
||||
|
||||
void Scheduler::RequestOutsideRenderPassOperationContext() {
|
||||
@@ -224,6 +242,28 @@ void Scheduler::RequestComputeDispatchContext() {
|
||||
compute_writes = true;
|
||||
}
|
||||
|
||||
void Scheduler::RelaxAttachmentOps(RenderingAttachments& attachments) const {
|
||||
const bool load_op_none = device.IsLoadOpNoneSupported();
|
||||
const auto relax = [&](VkRenderingAttachmentInfo& attachment, u32 bit) {
|
||||
if (attachment.imageView == VK_NULL_HANDLE ||
|
||||
attachment.resolveMode != VK_RESOLVE_MODE_NONE ||
|
||||
attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ||
|
||||
attachment.storeOp != VK_ATTACHMENT_STORE_OP_STORE ||
|
||||
(attachments_written & bit) != 0) {
|
||||
return;
|
||||
}
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_NONE;
|
||||
if (load_op_none && (attachments_touched & bit) == 0) {
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_NONE;
|
||||
}
|
||||
};
|
||||
for (u32 slot = 0; slot < attachments.num_colors; ++slot) {
|
||||
relax(attachments.colors[slot], 1u << slot);
|
||||
}
|
||||
relax(attachments.depth, DEPTH_ATTACHMENT_BIT);
|
||||
relax(attachments.stencil, STENCIL_ATTACHMENT_BIT);
|
||||
}
|
||||
|
||||
void Scheduler::PublishComputeWrites() {
|
||||
if (!std::exchange(compute_writes, false)) {
|
||||
return;
|
||||
@@ -406,6 +446,10 @@ void Scheduler::EndRenderPass()
|
||||
if (state.framebuffer_id == 0) {
|
||||
return;
|
||||
}
|
||||
if (recorded_attachments != nullptr) {
|
||||
RelaxAttachmentOps(*recorded_attachments);
|
||||
recorded_attachments = nullptr;
|
||||
}
|
||||
|
||||
query_cache->CounterClose(VideoCommon::QueryType::StreamingByteCount);
|
||||
|
||||
|
||||
@@ -42,6 +42,10 @@ struct RenderingAttachments;
|
||||
/// OpenGL-like operations on Vulkan command buffers.
|
||||
class Scheduler {
|
||||
public:
|
||||
static constexpr u32 DEPTH_ATTACHMENT_BIT = 1u << 8;
|
||||
static constexpr u32 STENCIL_ATTACHMENT_BIT = 1u << 9;
|
||||
static constexpr u32 ALL_ATTACHMENTS = 0x3FF;
|
||||
|
||||
explicit Scheduler(const Device& device, StateTracker& state_tracker);
|
||||
~Scheduler();
|
||||
|
||||
@@ -59,7 +63,8 @@ public:
|
||||
void DispatchWork();
|
||||
|
||||
/// Requests to begin a renderpass.
|
||||
void RequestRenderpass(const Framebuffer* framebuffer);
|
||||
void RequestRenderpass(const Framebuffer* framebuffer, u32 touched = ALL_ATTACHMENTS,
|
||||
u32 written = ALL_ATTACHMENTS);
|
||||
|
||||
/// Defers a full-attachment color clear so it becomes the next render pass.
|
||||
bool DeferColorClear(const Framebuffer* framebuffer, u32 rt_slot, const VkClearValue& value);
|
||||
@@ -100,12 +105,8 @@ public:
|
||||
renderpass_writes = true;
|
||||
}
|
||||
|
||||
void MarkDepthWrites(bool writes) noexcept {
|
||||
renderpass_depth_writes |= writes;
|
||||
}
|
||||
|
||||
bool HasDepthWrites() const noexcept {
|
||||
return renderpass_depth_writes;
|
||||
return (attachments_written & DEPTH_ATTACHMENT_BIT) != 0;
|
||||
}
|
||||
|
||||
/// Update the pipeline to the current execution context.
|
||||
@@ -235,6 +236,10 @@ private:
|
||||
command(cmdbuf, upload_cmdbuf);
|
||||
}
|
||||
|
||||
T& Get() noexcept {
|
||||
return command;
|
||||
}
|
||||
|
||||
private:
|
||||
T command;
|
||||
};
|
||||
@@ -244,16 +249,18 @@ private:
|
||||
void ExecuteAll(vk::CommandBuffer cmdbuf, vk::CommandBuffer upload_cmdbuf);
|
||||
|
||||
template <typename T>
|
||||
bool Record(T& command) {
|
||||
T* Record(T& command) {
|
||||
using FuncType = TypedCommand<T>;
|
||||
static_assert(sizeof(FuncType) < sizeof(data), "Lambda is too large");
|
||||
|
||||
command_offset = Common::AlignUp(command_offset, alignof(FuncType));
|
||||
if (command_offset > sizeof(data) - sizeof(FuncType)) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
Command* const current_last = last;
|
||||
last = new (data.data() + command_offset) FuncType(std::move(command));
|
||||
FuncType* const recorded =
|
||||
new (data.data() + command_offset) FuncType(std::move(command));
|
||||
last = recorded;
|
||||
|
||||
if (current_last) {
|
||||
current_last->SetNext(last);
|
||||
@@ -261,7 +268,7 @@ private:
|
||||
first = last;
|
||||
}
|
||||
command_offset += sizeof(FuncType);
|
||||
return true;
|
||||
return &recorded->Get();
|
||||
}
|
||||
|
||||
void MarkSubmit() {
|
||||
@@ -322,6 +329,8 @@ private:
|
||||
|
||||
void PublishComputeWrites();
|
||||
|
||||
void RelaxAttachmentOps(RenderingAttachments& attachments) const;
|
||||
|
||||
void AcquireNewChunk();
|
||||
|
||||
const Device& device;
|
||||
@@ -345,8 +354,10 @@ private:
|
||||
u64 renderpass_serial = 0;
|
||||
u64 wfi_serial = 0;
|
||||
bool renderpass_writes = false;
|
||||
bool renderpass_depth_writes = false;
|
||||
bool compute_writes = false;
|
||||
u32 attachments_touched = 0;
|
||||
u32 attachments_written = 0;
|
||||
RenderingAttachments* recorded_attachments = nullptr;
|
||||
VkMemoryBarrier2 renderpass_write_barrier{};
|
||||
VkMemoryBarrier2 compute_write_barrier{};
|
||||
VkMemoryBarrier2 upload_write_barrier{};
|
||||
|
||||
@@ -106,6 +106,8 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
||||
EXTENSION(KHR, SWAPCHAIN, swapchain) \
|
||||
EXTENSION(KHR, SWAPCHAIN_MUTABLE_FORMAT, swapchain_mutable_format) \
|
||||
EXTENSION(KHR, IMAGE_FORMAT_LIST, image_format_list) \
|
||||
EXTENSION(KHR, LOAD_STORE_OP_NONE, load_store_op_none) \
|
||||
EXTENSION(EXT, LOAD_STORE_OP_NONE, load_store_op_none_ext) \
|
||||
EXTENSION(NV, DEVICE_DIAGNOSTICS_CONFIG, device_diagnostics_config) \
|
||||
EXTENSION(NV, GEOMETRY_SHADER_PASSTHROUGH, geometry_shader_passthrough) \
|
||||
EXTENSION(NV, VIEWPORT_ARRAY2, viewport_array2) \
|
||||
@@ -669,6 +671,10 @@ FN_MAX_LIMIT_LIST
|
||||
}
|
||||
|
||||
/// Returns true if the device supports VK_EXT_depth_bias_control.
|
||||
bool IsLoadOpNoneSupported() const {
|
||||
return extensions.load_store_op_none || extensions.load_store_op_none_ext;
|
||||
}
|
||||
|
||||
bool IsExtDepthBiasControlSupported() const {
|
||||
return extensions.depth_bias_control;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user