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.
This commit is contained in:
Billy Laws 2022-09-02 11:58:50 +01:00
parent a6c49115f9
commit d1e7bbc1d8
2 changed files with 158 additions and 0 deletions

View File

@ -0,0 +1,43 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <gpu/buffer_manager.h>
#include <soc/gm20b/channel.h>
#include <soc/gm20b/gmmu.h>
#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> buffer, ContextLock<Buffer> &&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
}
}

View File

@ -0,0 +1,115 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <common/dirty_tracking.h>
#include <vulkan/vulkan_raii.hpp>
#include <soc/gm20b/engines/maxwell/types.h>
#include <gpu/buffer.h>
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<u8> 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<soc::gm20b::engine::EngineMethodsEnd * sizeof(u32), sizeof(u32)>;
/**
* @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<float, engine::BlendColorChannelCount> &blendConstants) {}
void SetDepthBounds(float minDepthBounds, float maxDepthBounds) {}
void SetBaseStencilState(vk::StencilFaceFlags flags, u32 funcRef, u32 funcMask, u32 mask) {}
};
}