Ensure correct flushing for batched constant buffer updates

Cbufs could be read by non-maxwell3D engines so force a flush when switching to them or before Execute.
This commit is contained in:
Billy Laws 2022-05-04 20:48:59 +01:00
parent ad989750fc
commit 03594a081c
5 changed files with 58 additions and 31 deletions

View File

@ -164,6 +164,10 @@ namespace skyline::gpu::interconnect {
} }
} }
void CommandExecutor::AddFlushCallback(std::function<void()> &&callback) {
flushCallbacks.emplace_back(std::forward<decltype(callback)>(callback));
}
void CommandExecutor::Execute() { void CommandExecutor::Execute() {
if (!nodes.empty()) { if (!nodes.empty()) {
TRACE_EVENT("gpu", "CommandExecutor::Execute"); TRACE_EVENT("gpu", "CommandExecutor::Execute");

View File

@ -29,6 +29,8 @@ namespace skyline::gpu::interconnect {
span<TextureView *> lastSubpassColorAttachments; //!< The set of color attachments used in the last subpass span<TextureView *> lastSubpassColorAttachments; //!< The set of color attachments used in the last subpass
TextureView *lastSubpassDepthStencilAttachment{}; //!< The depth stencil attachment used in the last subpass TextureView *lastSubpassDepthStencilAttachment{}; //!< The depth stencil attachment used in the last subpass
std::vector<std::function<void()>> flushCallbacks; //!< Set of persistent callbacks that will be called at the start of Execute in order to flush data required for recording
/** /**
* @brief Create a new render pass and subpass with the specified attachments, if one doesn't already exist or the current one isn't compatible * @brief Create a new render pass and subpass with the specified attachments, if one doesn't already exist or the current one isn't compatible
* @note This also checks for subpass coalescing and will merge the new subpass with the previous one when possible * @note This also checks for subpass coalescing and will merge the new subpass with the previous one when possible
@ -91,6 +93,11 @@ namespace skyline::gpu::interconnect {
*/ */
void AddOutsideRpCommand(std::function<void(vk::raii::CommandBuffer &, const std::shared_ptr<FenceCycle> &, GPU &)> &&function); void AddOutsideRpCommand(std::function<void(vk::raii::CommandBuffer &, const std::shared_ptr<FenceCycle> &, GPU &)> &&function);
/**
* @brief Adds a persistent callback that will be called at the start of Execute in order to flush data required for recording
*/
void AddFlushCallback(std::function<void()> &&callback);
/** /**
* @brief Execute all the nodes and submit the resulting command buffer to the GPU * @brief Execute all the nodes and submit the resulting command buffer to the GPU
*/ */

View File

@ -13,23 +13,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
context(*state.gpu, channelCtx, executor), context(*state.gpu, channelCtx, executor),
i2m(channelCtx.asCtx), i2m(channelCtx.asCtx),
channelCtx(channelCtx) { channelCtx(channelCtx) {
executor.AddFlushCallback([this]() { FlushEngineState(); });
InitializeRegisters(); InitializeRegisters();
} }
void Maxwell3D::CallMethodFromMacro(u32 method, u32 argument) {
HandleMethod(method, argument);
}
u32 Maxwell3D::ReadMethodFromMacro(u32 method) {
return registers.raw[method];
}
__attribute__((always_inline)) void Maxwell3D::CallMethod(u32 method, u32 argument) {
Logger::Verbose("Called method in Maxwell 3D: 0x{:X} args: 0x{:X}", method, argument);
HandleMethod(method, argument);
}
void Maxwell3D::HandleMethod(u32 method, u32 argument) { void Maxwell3D::HandleMethod(u32 method, u32 argument) {
if (method != ENGINE_STRUCT_OFFSET(mme, shadowRamControl)) { if (method != ENGINE_STRUCT_OFFSET(mme, shadowRamControl)) {
if (shadowRegisters.mme->shadowRamControl == type::MmeShadowRamControl::MethodTrack || shadowRegisters.mme->shadowRamControl == type::MmeShadowRamControl::MethodTrackWithFilter) if (shadowRegisters.mme->shadowRamControl == type::MmeShadowRamControl::MethodTrack || shadowRegisters.mme->shadowRamControl == type::MmeShadowRamControl::MethodTrackWithFilter)
@ -707,19 +694,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
} }
} }
void Maxwell3D::CallMethodBatchNonInc(u32 method, span<u32> arguments) {
switch (method) {
case ENGINE_STRUCT_OFFSET(i2m, loadInlineData):
i2m.LoadInlineData(*registers.i2m, arguments);
return;
default:
break;
}
for (u32 argument : arguments)
HandleMethod(method, argument);
}
void Maxwell3D::WriteSemaphoreResult(u64 result) { void Maxwell3D::WriteSemaphoreResult(u64 result) {
struct FourWordResult { struct FourWordResult {
u64 value; u64 value;
@ -745,4 +719,38 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
} }
} }
} }
void Maxwell3D::FlushEngineState() {
if (batchConstantBufferUpdate.Active()) {
context.ConstantBufferUpdate(std::move(batchConstantBufferUpdate.buffer), batchConstantBufferUpdate.startOffset);
batchConstantBufferUpdate.Reset();
}
}
__attribute__((always_inline)) void Maxwell3D::CallMethod(u32 method, u32 argument) {
Logger::Verbose("Called method in Maxwell 3D: 0x{:X} args: 0x{:X}", method, argument);
HandleMethod(method, argument);
}
void Maxwell3D::CallMethodBatchNonInc(u32 method, span<u32> arguments) {
switch (method) {
case ENGINE_STRUCT_OFFSET(i2m, loadInlineData):
i2m.LoadInlineData(*registers.i2m, arguments);
return;
default:
break;
}
for (u32 argument : arguments)
HandleMethod(method, argument);
}
void Maxwell3D::CallMethodFromMacro(u32 method, u32 argument) {
HandleMethod(method, argument);
}
u32 Maxwell3D::ReadMethodFromMacro(u32 method) {
return registers.raw[method];
}
} }

View File

@ -356,7 +356,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
ChannelContext &channelCtx; ChannelContext &channelCtx;
Maxwell3D(const DeviceState &state, ChannelContext &channelCtx, MacroState &macroState, gpu::interconnect::CommandExecutor &executor); Maxwell3D(const DeviceState &state, ChannelContext &channelCtx, MacroState &macroState, gpu::interconnect::CommandExecutor &executor);
/** /**
@ -364,6 +363,11 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
*/ */
void InitializeRegisters(); void InitializeRegisters();
/**
* @brief Flushes any batched constant buffer update or instanced draw state
*/
void FlushEngineState();
void CallMethod(u32 method, u32 argument); void CallMethod(u32 method, u32 argument);
void CallMethodBatchNonInc(u32 method, span<u32> arguments); void CallMethodBatchNonInc(u32 method, span<u32> arguments);

View File

@ -322,15 +322,19 @@ namespace skyline::soc::gm20b {
}}; }};
bool hitEnd{[&]() { bool hitEnd{[&]() {
if (methodHeader.methodSubChannel == SubchannelId::ThreeD) [[likely]] if (methodHeader.methodSubChannel == SubchannelId::ThreeD) { [[likely]]
return processMethod.operator()<true>(); return processMethod.operator()<true>();
else } else {
channelCtx.maxwell3D->FlushEngineState(); // Flush the 3D engine state when doing any calls to other engines
return processMethod.operator()<false>(); return processMethod.operator()<false>();
}
}()}; }()};
if (hitEnd) if (hitEnd)
return; break;
} }
channelCtx.maxwell3D->FlushEngineState();
} }
void ChannelGpfifo::Run() { void ChannelGpfifo::Run() {