From d1e7bbc1d8d71d02469d0f06cec8652884485444 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Fri, 2 Sep 2022 11:58:50 +0100 Subject: [PATCH] Introduce common code for Maxwell 3D interconnect rewrite This common code will be used across the entirety of the 3D rewrite, it also includes a stub for StateUpdateBuilder, which will be used by active state code to apply state updates. --- .../gpu/interconnect/maxwell_3d/common.cpp | 43 +++++++ .../gpu/interconnect/maxwell_3d/common.h | 115 ++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/common.cpp create mode 100644 app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/common.h diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/common.cpp b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/common.cpp new file mode 100644 index 00000000..e548a564 --- /dev/null +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/common.cpp @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#include +#include +#include +#include "common.h" + +namespace skyline::gpu::interconnect::maxwell3d { + void CachedMappedBufferView::Update(InterconnectContext &ctx, u64 address, u64 size, bool splitMappingWarn) { + // Ignore size for the mapping end check here as we don't support buffers split across multiple mappings so only the first one would be used anyway. It's also impossible for the mapping to have been remapped with a larger one since the original lookup because the we force the mapping to be reset after semaphores + if (address < blockMappingStartAddr || address >= blockMappingEndAddr) { + u64 blockOffset{}; + std::tie(blockMapping, blockOffset) = ctx.channelCtx.asCtx->gmmu.LookupBlock(address); + blockMappingStartAddr = address - blockOffset; + blockMappingEndAddr = blockMappingStartAddr + blockMapping.size(); + } + + // Mapping from the start of the buffer view to the end of the block + auto fullMapping{blockMapping.subspan(address - blockMappingStartAddr)}; + + if (splitMappingWarn && fullMapping.size() < size) + Logger::Warn("Split buffer mappings are not supported"); + + // Mapping covering just the requested input view (or less in the case of split mappings) + auto viewMapping{fullMapping.first(std::min(fullMapping.size(), size))}; + + // First attempt to skip lookup by trying to reuse the previous view's underlying buffer + if (view) + if (view = view.GetBuffer()->TryGetView(viewMapping); view) + return; + + // Otherwise perform a full lookup + view = ctx.executor.AcquireBufferManager().FindOrCreate(viewMapping, ctx.executor.tag, [&ctx](std::shared_ptr buffer, ContextLock &&lock) { + ctx.executor.AttachLockedBuffer(buffer, std::move(lock)); + }); + } + + void CachedMappedBufferView::PurgeCaches() { + view = {}; + blockMappingEndAddr = 0; // Will force a retranslate of `blockMapping` on the next `Update()` call + } +} diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/common.h b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/common.h new file mode 100644 index 00000000..8593f0bc --- /dev/null +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/common.h @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include +#include +#include +#include + +namespace skyline::soc::gm20b { + struct ChannelContext; +} + +namespace skyline::gpu::interconnect { + class CommandExecutor; +} + +namespace skyline::gpu::interconnect::maxwell3d { + namespace engine = skyline::soc::gm20b::engine::maxwell3d::type; + + /** + * @brief Holds GPU context for an interconnect instance + */ + struct InterconnectContext { + soc::gm20b::ChannelContext &channelCtx; + CommandExecutor &executor; + GPU &gpu; + }; + + /** + * @brief Helper around a buffer view that performs caching based on the underlying GPU mappings + */ + class CachedMappedBufferView { + private: + span blockMapping; //!< The underlying mapping that `view` is a part of + u64 blockMappingStartAddr; //!< The start GPU address of `blockMapping` + u64 blockMappingEndAddr; //!< The end GPU address of `blockMapping` + + public: + BufferView view; //!< The buffer view created as a result of a call to `Update()` + + /** + * @brief Updates `view` based on the supplied GPU mapping + */ + void Update(InterconnectContext &ctx, u64 address, u64 size, bool splitMappingWarn = true); + + /** + * @brief Purges the cached block mapping so the next `Update()` call will perform a full lookup + */ + void PurgeCaches(); + + BufferView &operator*() { + return view; + } + + BufferView *operator->() { + return &view; + } + }; + + /** + * @brief Represents a bound Vulkan buffer that can be used for state updates + */ + struct BufferBinding { + vk::Buffer buffer{}; + vk::DeviceSize offset{}; + vk::DeviceSize size{}; + + BufferBinding() = default; + + BufferBinding(vk::Buffer buffer, vk::DeviceSize offset = 0, vk::DeviceSize size = 0) : buffer{buffer}, offset{offset}, size{size} {} + }; + + using DirtyManager = dirty::Manager; + + /** + * @brief This is a stub for a future implementation + */ + struct StateUpdateBuilder { + void SetVertexBuffer(u32 index, BufferBinding *binding) {} + + void SetVertexBuffer(u32 index, BufferView &view) { + view.GetBuffer()->BlockSequencedCpuBackingWrites(); + } + + void SetIndexBuffer(BufferBinding *binding, vk::IndexType indexType) {} + + void SetIndexBuffer(BufferView &view, vk::IndexType indexType) { + view.GetBuffer()->BlockSequencedCpuBackingWrites(); + + } + + void SetTransformFeedbackBuffer(u32 index, BufferView &view) { + view.GetBuffer()->BlockSequencedCpuBackingWrites(); + + } + + void SetTransformFeedbackBuffer(u32 index, BufferBinding *binding) {} + + void SetViewport(u32 index, const vk::Viewport &viewport) {} + + void SetScissor(u32 index, const vk::Rect2D &scissor) {} + + void SetLineWidth(float lineWidth) {} + + void SetDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {} + + void SetBlendConstants(const std::array &blendConstants) {} + + void SetDepthBounds(float minDepthBounds, float maxDepthBounds) {} + + void SetBaseStencilState(vk::StencilFaceFlags flags, u32 funcRef, u32 funcMask, u32 mask) {} + }; +}