mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 17:55:28 +03:00
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:
parent
ad989750fc
commit
03594a081c
@ -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");
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,7 +356,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
|
|
||||||
ChannelContext &channelCtx;
|
ChannelContext &channelCtx;
|
||||||
|
|
||||||
|
|
||||||
Maxwell3D(const DeviceState &state, ChannelContext &channelCtx, MacroState ¯oState, gpu::interconnect::CommandExecutor &executor);
|
Maxwell3D(const DeviceState &state, ChannelContext &channelCtx, MacroState ¯oState, 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);
|
||||||
|
@ -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() {
|
||||||
|
Loading…
Reference in New Issue
Block a user