mirror of
https://github.com/skyline-emu/skyline.git
synced 2025-03-04 03:15:20 +03:00
Remove now redundant buffer/texture/megabuffer manager locks
They have been superseeded by the global channel lock
This commit is contained in:
parent
f5a141a621
commit
05581f2230
@ -11,18 +11,6 @@ namespace skyline::gpu {
|
|||||||
return it->guest->begin().base() < pointer;
|
return it->guest->begin().base() < pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferManager::lock() {
|
|
||||||
mutex.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferManager::unlock() {
|
|
||||||
mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BufferManager::try_lock() {
|
|
||||||
return mutex.try_lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferManager::LockedBuffer::LockedBuffer(std::shared_ptr<Buffer> pBuffer, ContextTag tag) : buffer{std::move(pBuffer)}, lock{tag, *buffer}, stateLock(buffer->stateMutex) {}
|
BufferManager::LockedBuffer::LockedBuffer(std::shared_ptr<Buffer> pBuffer, ContextTag tag) : buffer{std::move(pBuffer)}, lock{tag, *buffer}, stateLock(buffer->stateMutex) {}
|
||||||
|
|
||||||
Buffer *BufferManager::LockedBuffer::operator->() const {
|
Buffer *BufferManager::LockedBuffer::operator->() const {
|
||||||
|
@ -15,7 +15,6 @@ namespace skyline::gpu {
|
|||||||
class BufferManager {
|
class BufferManager {
|
||||||
private:
|
private:
|
||||||
GPU &gpu;
|
GPU &gpu;
|
||||||
std::mutex mutex; //!< Synchronizes access to the buffer mappings
|
|
||||||
std::vector<std::shared_ptr<Buffer>> bufferMappings; //!< A sorted vector of all buffer mappings
|
std::vector<std::shared_ptr<Buffer>> bufferMappings; //!< A sorted vector of all buffer mappings
|
||||||
LinearAllocatorState<> delegateAllocatorState; //!< Linear allocator used to allocate buffer delegates
|
LinearAllocatorState<> delegateAllocatorState; //!< Linear allocator used to allocate buffer delegates
|
||||||
size_t nextBufferId{}; //!< The next unique buffer id to be assigned
|
size_t nextBufferId{}; //!< The next unique buffer id to be assigned
|
||||||
|
@ -126,33 +126,18 @@ namespace skyline::gpu::interconnect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CommandExecutor::RotateRecordSlot() {
|
void CommandExecutor::RotateRecordSlot() {
|
||||||
if (slot)
|
if (slot) {
|
||||||
|
slot->capt = capt;
|
||||||
recordThread.ReleaseSlot(slot);
|
recordThread.ReleaseSlot(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
capt = false;
|
||||||
slot = recordThread.AcquireSlot();
|
slot = recordThread.AcquireSlot();
|
||||||
cycle = slot->Reset(gpu);
|
cycle = slot->Reset(gpu);
|
||||||
slot->executionNumber = executionNumber;
|
slot->executionNumber = executionNumber;
|
||||||
allocator = &slot->allocator;
|
allocator = &slot->allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureManager &CommandExecutor::AcquireTextureManager() {
|
|
||||||
if (!textureManagerLock)
|
|
||||||
textureManagerLock.emplace(gpu.texture);
|
|
||||||
return gpu.texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferManager &CommandExecutor::AcquireBufferManager() {
|
|
||||||
if (!bufferManagerLock)
|
|
||||||
bufferManagerLock.emplace(gpu.buffer);
|
|
||||||
return gpu.buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
MegaBufferAllocator &CommandExecutor::AcquireMegaBufferAllocator() {
|
|
||||||
if (!megaBufferAllocatorLock)
|
|
||||||
megaBufferAllocatorLock.emplace(gpu.megaBufferAllocator);
|
|
||||||
return gpu.megaBufferAllocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CommandExecutor::CreateRenderPassWithSubpass(vk::Rect2D renderArea, span<TextureView *> inputAttachments, span<TextureView *> colorAttachments, TextureView *depthStencilAttachment, bool noSubpassCreation) {
|
bool CommandExecutor::CreateRenderPassWithSubpass(vk::Rect2D renderArea, span<TextureView *> inputAttachments, span<TextureView *> colorAttachments, TextureView *depthStencilAttachment, bool noSubpassCreation) {
|
||||||
auto addSubpass{[&] {
|
auto addSubpass{[&] {
|
||||||
renderPass->AddSubpass(inputAttachments, colorAttachments, depthStencilAttachment, gpu);
|
renderPass->AddSubpass(inputAttachments, colorAttachments, depthStencilAttachment, gpu);
|
||||||
@ -230,10 +215,6 @@ namespace skyline::gpu::interconnect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CommandExecutor::AttachTexture(TextureView *view) {
|
bool CommandExecutor::AttachTexture(TextureView *view) {
|
||||||
if (!textureManagerLock)
|
|
||||||
// Avoids a potential deadlock with this resource being locked while acquiring the TextureManager lock while the thread owning it tries to acquire a lock on this texture
|
|
||||||
textureManagerLock.emplace(gpu.texture);
|
|
||||||
|
|
||||||
bool didLock{view->LockWithTag(tag)};
|
bool didLock{view->LockWithTag(tag)};
|
||||||
if (didLock) {
|
if (didLock) {
|
||||||
if (view->texture->FrequentlyLocked())
|
if (view->texture->FrequentlyLocked())
|
||||||
@ -259,10 +240,6 @@ namespace skyline::gpu::interconnect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CommandExecutor::AttachBuffer(BufferView &view) {
|
bool CommandExecutor::AttachBuffer(BufferView &view) {
|
||||||
if (!bufferManagerLock)
|
|
||||||
// See AttachTexture(...)
|
|
||||||
bufferManagerLock.emplace(gpu.buffer);
|
|
||||||
|
|
||||||
bool didLock{view.LockWithTag(tag)};
|
bool didLock{view.LockWithTag(tag)};
|
||||||
if (didLock) {
|
if (didLock) {
|
||||||
if (view.GetBuffer()->FrequentlyLocked())
|
if (view.GetBuffer()->FrequentlyLocked())
|
||||||
@ -274,10 +251,6 @@ namespace skyline::gpu::interconnect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CommandExecutor::AttachLockedBufferView(BufferView &view, ContextLock<BufferView> &&lock) {
|
void CommandExecutor::AttachLockedBufferView(BufferView &view, ContextLock<BufferView> &&lock) {
|
||||||
if (!bufferManagerLock)
|
|
||||||
// See AttachTexture(...)
|
|
||||||
bufferManagerLock.emplace(gpu.buffer);
|
|
||||||
|
|
||||||
if (lock.OwnsLock()) {
|
if (lock.OwnsLock()) {
|
||||||
// Transfer ownership to executor so that the resource will stay locked for the period it is used on the GPU
|
// Transfer ownership to executor so that the resource will stay locked for the period it is used on the GPU
|
||||||
if (view.GetBuffer()->FrequentlyLocked())
|
if (view.GetBuffer()->FrequentlyLocked())
|
||||||
@ -423,10 +396,7 @@ namespace skyline::gpu::interconnect {
|
|||||||
|
|
||||||
void CommandExecutor::ResetInternal() {
|
void CommandExecutor::ResetInternal() {
|
||||||
attachedTextures.clear();
|
attachedTextures.clear();
|
||||||
textureManagerLock.reset();
|
|
||||||
attachedBuffers.clear();
|
attachedBuffers.clear();
|
||||||
bufferManagerLock.reset();
|
|
||||||
megaBufferAllocatorLock.reset();
|
|
||||||
allocator->Reset();
|
allocator->Reset();
|
||||||
|
|
||||||
// Periodically clear preserve attachments just in case there are new waiters which would otherwise end up waiting forever
|
// Periodically clear preserve attachments just in case there are new waiters which would otherwise end up waiting forever
|
||||||
|
@ -74,9 +74,6 @@ namespace skyline::gpu::interconnect {
|
|||||||
CommandRecordThread::Slot *slot{};
|
CommandRecordThread::Slot *slot{};
|
||||||
node::RenderPassNode *renderPass{};
|
node::RenderPassNode *renderPass{};
|
||||||
size_t subpassCount{}; //!< The number of subpasses in the current render pass
|
size_t subpassCount{}; //!< The number of subpasses in the current render pass
|
||||||
std::optional<std::scoped_lock<TextureManager>> textureManagerLock; //!< The lock on the texture manager, this is locked for the duration of the command execution from the first usage inside an execution to the submission
|
|
||||||
std::optional<std::scoped_lock<BufferManager>> bufferManagerLock; //!< The lock on the buffer manager, see above for details
|
|
||||||
std::optional<std::scoped_lock<MegaBufferAllocator>> megaBufferAllocatorLock; //!< The lock on the megabuffer allocator, see above for details
|
|
||||||
bool preserveLocked{};
|
bool preserveLocked{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,17 +157,12 @@ namespace skyline::gpu::interconnect {
|
|||||||
ContextTag tag; //!< The tag associated with this command executor, any tagged resource locking must utilize this tag
|
ContextTag tag; //!< The tag associated with this command executor, any tagged resource locking must utilize this tag
|
||||||
size_t submissionNumber{};
|
size_t submissionNumber{};
|
||||||
u32 executionNumber{};
|
u32 executionNumber{};
|
||||||
|
bool capt{};
|
||||||
|
|
||||||
CommandExecutor(const DeviceState &state);
|
CommandExecutor(const DeviceState &state);
|
||||||
|
|
||||||
~CommandExecutor();
|
~CommandExecutor();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return A reference to an instance of the Texture Manager which will be locked till execution
|
|
||||||
* @note Any access to the texture manager while recording commands **must** be done via this
|
|
||||||
*/
|
|
||||||
TextureManager &AcquireTextureManager();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Attach the lifetime of the texture to the command buffer
|
* @brief Attach the lifetime of the texture to the command buffer
|
||||||
* @return If this is the first usage of the backing of this resource within this execution
|
* @return If this is the first usage of the backing of this resource within this execution
|
||||||
@ -179,12 +171,6 @@ namespace skyline::gpu::interconnect {
|
|||||||
*/
|
*/
|
||||||
bool AttachTexture(TextureView *view);
|
bool AttachTexture(TextureView *view);
|
||||||
|
|
||||||
/**
|
|
||||||
* @return A reference to an instance of the Buffer Manager which will be locked till execution
|
|
||||||
* @note Any access to the buffer manager while recording commands **must** be done via this
|
|
||||||
*/
|
|
||||||
BufferManager &AcquireBufferManager();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Attach the lifetime of a buffer view to the command buffer
|
* @brief Attach the lifetime of a buffer view to the command buffer
|
||||||
* @return If this is the first usage of the backing of this resource within this execution
|
* @return If this is the first usage of the backing of this resource within this execution
|
||||||
@ -193,12 +179,6 @@ namespace skyline::gpu::interconnect {
|
|||||||
*/
|
*/
|
||||||
bool AttachBuffer(BufferView &view);
|
bool AttachBuffer(BufferView &view);
|
||||||
|
|
||||||
/**
|
|
||||||
* @return A reference to an instance of the megabuffer allocator which will be locked till execution
|
|
||||||
* @note Any access to the megabuffer allocator while recording commands **must** be done via this
|
|
||||||
*/
|
|
||||||
MegaBufferAllocator &AcquireMegaBufferAllocator();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Attach the lifetime of a buffer view that's already locked to the command buffer
|
* @brief Attach the lifetime of a buffer view that's already locked to the command buffer
|
||||||
* @note The supplied buffer **must** be locked with the executor's tag
|
* @note The supplied buffer **must** be locked with the executor's tag
|
||||||
|
@ -113,11 +113,10 @@ namespace skyline::gpu::interconnect {
|
|||||||
auto srcGuestTexture{GetGuestTexture(srcSurface)};
|
auto srcGuestTexture{GetGuestTexture(srcSurface)};
|
||||||
auto dstGuestTexture{GetGuestTexture(dstSurface)};
|
auto dstGuestTexture{GetGuestTexture(dstSurface)};
|
||||||
|
|
||||||
auto &textureManager{executor.AcquireTextureManager()};
|
auto srcTextureView{gpu.texture.FindOrCreate(srcGuestTexture, executor.tag)};
|
||||||
auto srcTextureView{textureManager.FindOrCreate(srcGuestTexture, executor.tag)};
|
|
||||||
executor.AttachTexture(srcTextureView.get());
|
executor.AttachTexture(srcTextureView.get());
|
||||||
|
|
||||||
auto dstTextureView{textureManager.FindOrCreate(dstGuestTexture, executor.tag)};
|
auto dstTextureView{gpu.texture.FindOrCreate(dstGuestTexture, executor.tag)};
|
||||||
executor.AttachTexture(dstTextureView.get());
|
executor.AttachTexture(dstTextureView.get());
|
||||||
|
|
||||||
// Blit shader always samples from centre so adjust if necessary
|
// Blit shader always samples from centre so adjust if necessary
|
||||||
|
@ -745,7 +745,7 @@ namespace skyline::gpu::interconnect {
|
|||||||
void ConstantBufferUpdate(span<u32> data, u32 offset) {
|
void ConstantBufferUpdate(span<u32> data, u32 offset) {
|
||||||
auto constantBuffer{GetConstantBufferSelector()};
|
auto constantBuffer{GetConstantBufferSelector()};
|
||||||
if (constantBuffer)
|
if (constantBuffer)
|
||||||
constantBuffer->Write<u32>(executor, executor.AcquireMegaBufferAllocator(), data, offset);
|
constantBuffer->Write<u32>(executor, gpu.megaBufferAllocator, data, offset);
|
||||||
else
|
else
|
||||||
throw exception("Attempting to write to invalid constant buffer!");
|
throw exception("Attempting to write to invalid constant buffer!");
|
||||||
}
|
}
|
||||||
@ -1148,7 +1148,7 @@ namespace skyline::gpu::interconnect {
|
|||||||
|
|
||||||
auto &view{*pipelineStage.constantBuffers[constantBuffer.index].view};
|
auto &view{*pipelineStage.constantBuffers[constantBuffer.index].view};
|
||||||
executor.AttachBuffer(view);
|
executor.AttachBuffer(view);
|
||||||
if (auto megaBufferAllocation{view.AcquireMegaBuffer(executor.cycle, executor.AcquireMegaBufferAllocator())}) {
|
if (auto megaBufferAllocation{view.AcquireMegaBuffer(executor.cycle, gpu.megaBufferAllocator)}) {
|
||||||
// If the buffer is megabuffered then since we don't get out data from the underlying buffer, rather the megabuffer which stays consistent throughout a single execution, we can skip registering usage
|
// If the buffer is megabuffered then since we don't get out data from the underlying buffer, rather the megabuffer which stays consistent throughout a single execution, we can skip registering usage
|
||||||
bufferDescriptors[bufferIndex] = vk::DescriptorBufferInfo{
|
bufferDescriptors[bufferIndex] = vk::DescriptorBufferInfo{
|
||||||
.buffer = megaBufferAllocation.buffer,
|
.buffer = megaBufferAllocation.buffer,
|
||||||
@ -1741,7 +1741,7 @@ namespace skyline::gpu::interconnect {
|
|||||||
*/
|
*/
|
||||||
MegaBufferAllocator::Allocation GetIndexedQuadConversionBuffer(u32 count, u32 first) {
|
MegaBufferAllocator::Allocation GetIndexedQuadConversionBuffer(u32 count, u32 first) {
|
||||||
vk::DeviceSize size{conversion::quads::GetRequiredBufferSize(count, indexBuffer.GetIndexSize())};
|
vk::DeviceSize size{conversion::quads::GetRequiredBufferSize(count, indexBuffer.GetIndexSize())};
|
||||||
auto allocation{executor.AcquireMegaBufferAllocator().Allocate(executor.cycle, size)};
|
auto allocation{gpu.megaBufferAllocator.Allocate(executor.cycle, size)};
|
||||||
|
|
||||||
ContextLock lock{executor.tag, indexBuffer.view};
|
ContextLock lock{executor.tag, indexBuffer.view};
|
||||||
auto guestIndexBuffer{indexBuffer.view.GetReadOnlyBackingSpan(lock.IsFirstUsage(), []() {
|
auto guestIndexBuffer{indexBuffer.view.GetReadOnlyBackingSpan(lock.IsFirstUsage(), []() {
|
||||||
@ -3045,7 +3045,7 @@ namespace skyline::gpu::interconnect {
|
|||||||
executor.AttachBuffer(indexBufferView);
|
executor.AttachBuffer(indexBufferView);
|
||||||
|
|
||||||
boundIndexBuffer->type = indexBuffer.type;
|
boundIndexBuffer->type = indexBuffer.type;
|
||||||
if (auto megaBufferAllocation{indexBufferView.AcquireMegaBuffer(executor.cycle, executor.AcquireMegaBufferAllocator())}) {
|
if (auto megaBufferAllocation{indexBufferView.AcquireMegaBuffer(executor.cycle, gpu.megaBufferAllocator)}) {
|
||||||
// If the buffer is megabuffered then since we don't get out data from the underlying buffer, rather the megabuffer which stays consistent throughout a single execution, we can skip registering usage
|
// If the buffer is megabuffered then since we don't get out data from the underlying buffer, rather the megabuffer which stays consistent throughout a single execution, we can skip registering usage
|
||||||
boundIndexBuffer->handle = megaBufferAllocation.buffer;
|
boundIndexBuffer->handle = megaBufferAllocation.buffer;
|
||||||
boundIndexBuffer->offset = megaBufferAllocation.offset;
|
boundIndexBuffer->offset = megaBufferAllocation.offset;
|
||||||
@ -3088,7 +3088,7 @@ namespace skyline::gpu::interconnect {
|
|||||||
|
|
||||||
auto &vertexBufferView{vertexBuffer->view};
|
auto &vertexBufferView{vertexBuffer->view};
|
||||||
executor.AttachBuffer(vertexBufferView);
|
executor.AttachBuffer(vertexBufferView);
|
||||||
if (auto megaBufferAllocation{vertexBufferView.AcquireMegaBuffer(executor.cycle, executor.AcquireMegaBufferAllocator())}) {
|
if (auto megaBufferAllocation{vertexBufferView.AcquireMegaBuffer(executor.cycle, gpu.megaBufferAllocator)}) {
|
||||||
// If the buffer is megabuffered then since we don't get out data from the underlying buffer, rather the megabuffer which stays consistent throughout a single execution, we can skip registering usage
|
// If the buffer is megabuffered then since we don't get out data from the underlying buffer, rather the megabuffer which stays consistent throughout a single execution, we can skip registering usage
|
||||||
boundVertexBuffers->handles[index] = megaBufferAllocation.buffer;
|
boundVertexBuffers->handles[index] = megaBufferAllocation.buffer;
|
||||||
boundVertexBuffers->offsets[index] = megaBufferAllocation.offset;
|
boundVertexBuffers->offsets[index] = megaBufferAllocation.offset;
|
||||||
|
@ -29,7 +29,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
if (*view) {
|
if (*view) {
|
||||||
ctx.executor.AttachBuffer(*view);
|
ctx.executor.AttachBuffer(*view);
|
||||||
|
|
||||||
if (megaBufferBinding = view->TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber);
|
if (megaBufferBinding = view->TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionNumber);
|
||||||
megaBufferBinding)
|
megaBufferBinding)
|
||||||
builder.SetVertexBuffer(index, megaBufferBinding);
|
builder.SetVertexBuffer(index, megaBufferBinding);
|
||||||
else
|
else
|
||||||
@ -43,12 +43,12 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
|
|
||||||
// TODO: null descriptor
|
// TODO: null descriptor
|
||||||
megaBufferBinding = {};
|
megaBufferBinding = {};
|
||||||
builder.SetVertexBuffer(index, {ctx.executor.AcquireMegaBufferAllocator().Allocate(ctx.executor.cycle, 0).buffer});
|
builder.SetVertexBuffer(index, {ctx.gpu.megaBufferAllocator.Allocate(ctx.executor.cycle, 0).buffer});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VertexBufferState::Refresh(InterconnectContext &ctx, StateUpdateBuilder &builder) {
|
bool VertexBufferState::Refresh(InterconnectContext &ctx, StateUpdateBuilder &builder) {
|
||||||
if (megaBufferBinding) {
|
if (megaBufferBinding) {
|
||||||
if (auto newMegaBufferBinding{view->TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber)};
|
if (auto newMegaBufferBinding{view->TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionNumber)};
|
||||||
newMegaBufferBinding != megaBufferBinding) {
|
newMegaBufferBinding != megaBufferBinding) {
|
||||||
|
|
||||||
megaBufferBinding = newMegaBufferBinding;
|
megaBufferBinding = newMegaBufferBinding;
|
||||||
@ -101,7 +101,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
|
|
||||||
size_t indexSize{1U << static_cast<u32>(indexType)};
|
size_t indexSize{1U << static_cast<u32>(indexType)};
|
||||||
vk::DeviceSize indexBufferSize{conversion::quads::GetRequiredBufferSize(elementCount, indexSize)};
|
vk::DeviceSize indexBufferSize{conversion::quads::GetRequiredBufferSize(elementCount, indexSize)};
|
||||||
auto quadConversionAllocation{ctx.executor.AcquireMegaBufferAllocator().Allocate(ctx.executor.cycle, indexBufferSize)};
|
auto quadConversionAllocation{ctx.gpu.megaBufferAllocator.Allocate(ctx.executor.cycle, indexBufferSize)};
|
||||||
|
|
||||||
conversion::quads::GenerateIndexedQuadConversionBuffer(quadConversionAllocation.region.data(), viewSpan.data(), elementCount, ConvertIndexType(indexType));
|
conversion::quads::GenerateIndexedQuadConversionBuffer(quadConversionAllocation.region.data(), viewSpan.data(), elementCount, ConvertIndexType(indexType));
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
if (quadConversion)
|
if (quadConversion)
|
||||||
megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, engine->indexBuffer.indexSize, *view, elementCount);
|
megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, engine->indexBuffer.indexSize, *view, elementCount);
|
||||||
else
|
else
|
||||||
megaBufferBinding = view->TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber);
|
megaBufferBinding = view->TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionNumber);
|
||||||
|
|
||||||
if (megaBufferBinding)
|
if (megaBufferBinding)
|
||||||
builder.SetIndexBuffer(megaBufferBinding, indexType);
|
builder.SetIndexBuffer(megaBufferBinding, indexType);
|
||||||
@ -153,7 +153,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, engine->indexBuffer.indexSize, *view, elementCount);
|
megaBufferBinding = GenerateQuadConversionIndexBuffer(ctx, engine->indexBuffer.indexSize, *view, elementCount);
|
||||||
builder.SetIndexBuffer(megaBufferBinding, indexType);
|
builder.SetIndexBuffer(megaBufferBinding, indexType);
|
||||||
} else if (megaBufferBinding) {
|
} else if (megaBufferBinding) {
|
||||||
if (auto newMegaBufferBinding{view->TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber)};
|
if (auto newMegaBufferBinding{view->TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionNumber)};
|
||||||
newMegaBufferBinding != megaBufferBinding) {
|
newMegaBufferBinding != megaBufferBinding) {
|
||||||
|
|
||||||
megaBufferBinding = newMegaBufferBinding;
|
megaBufferBinding = newMegaBufferBinding;
|
||||||
@ -196,7 +196,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bind an empty buffer ourselves since Vulkan doesn't support passing a VK_NULL_HANDLE xfb buffer
|
// Bind an empty buffer ourselves since Vulkan doesn't support passing a VK_NULL_HANDLE xfb buffer
|
||||||
builder.SetTransformFeedbackBuffer(index, {ctx.executor.AcquireMegaBufferAllocator().Allocate(ctx.executor.cycle, 0).buffer});
|
builder.SetTransformFeedbackBuffer(index, {ctx.gpu.megaBufferAllocator.Allocate(ctx.executor.cycle, 0).buffer});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Otherwise perform a full lookup
|
// Otherwise perform a full lookup
|
||||||
view = ctx.executor.AcquireBufferManager().FindOrCreate(viewMapping, ctx.executor.tag, [&ctx](std::shared_ptr<Buffer> buffer, ContextLock<Buffer> &&lock) {
|
view = ctx.gpu.buffer.FindOrCreate(viewMapping, ctx.executor.tag, [&ctx](std::shared_ptr<Buffer> buffer, ContextLock<Buffer> &&lock) {
|
||||||
ctx.executor.AttachLockedBuffer(buffer, std::move(lock));
|
ctx.executor.AttachLockedBuffer(buffer, std::move(lock));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConstantBuffer::Read(CommandExecutor &executor, span<u8> dstBuffer, size_t srcOffset) {
|
void ConstantBuffer::Read(CommandExecutor &executor, span<u8> dstBuffer, size_t srcOffset) {
|
||||||
executor.AcquireBufferManager();
|
|
||||||
ContextLock lock{executor.tag, view};
|
ContextLock lock{executor.tag, view};
|
||||||
view.Read(lock.IsFirstUsage(), FlushHostCallback, dstBuffer, srcOffset);
|
view.Read(lock.IsFirstUsage(), FlushHostCallback, dstBuffer, srcOffset);
|
||||||
}
|
}
|
||||||
@ -54,7 +53,6 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
auto &view{*selectorState.UpdateGet(ctx, data.size_bytes()).view};
|
auto &view{*selectorState.UpdateGet(ctx, data.size_bytes()).view};
|
||||||
auto srcCpuBuf{data.cast<u8>()};
|
auto srcCpuBuf{data.cast<u8>()};
|
||||||
|
|
||||||
ctx.executor.AcquireBufferManager();
|
|
||||||
ContextLock lock{ctx.executor.tag, view};
|
ContextLock lock{ctx.executor.tag, view};
|
||||||
|
|
||||||
// First attempt the write without setting up the gpu copy callback as a fast path
|
// First attempt the write without setting up the gpu copy callback as a fast path
|
||||||
@ -73,7 +71,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
// This will prevent any CPU accesses to backing for the duration of the usage
|
// This will prevent any CPU accesses to backing for the duration of the usage
|
||||||
callbackData.view.GetBuffer()->BlockAllCpuBackingWrites();
|
callbackData.view.GetBuffer()->BlockAllCpuBackingWrites();
|
||||||
|
|
||||||
auto srcGpuAllocation{callbackData.ctx.executor.AcquireMegaBufferAllocator().Push(callbackData.ctx.executor.cycle, callbackData.srcCpuBuf)};
|
auto srcGpuAllocation{callbackData.ctx.gpu.megaBufferAllocator.Push(callbackData.ctx.executor.cycle, callbackData.srcCpuBuf)};
|
||||||
callbackData.ctx.executor.AddOutsideRpCommand([=, srcCpuBuf = callbackData.srcCpuBuf, view = callbackData.view, offset = callbackData.offset](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &, GPU &) {
|
callbackData.ctx.executor.AddOutsideRpCommand([=, srcCpuBuf = callbackData.srcCpuBuf, view = callbackData.view, offset = callbackData.offset](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &, GPU &) {
|
||||||
vk::BufferCopy copyRegion{
|
vk::BufferCopy copyRegion{
|
||||||
.size = srcCpuBuf.size_bytes(),
|
.size = srcCpuBuf.size_bytes(),
|
||||||
|
@ -617,12 +617,12 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
|
|
||||||
static DynamicBufferBinding GetConstantBufferBinding(InterconnectContext &ctx, const Shader::Info &info, BufferView view, size_t idx) {
|
static DynamicBufferBinding GetConstantBufferBinding(InterconnectContext &ctx, const Shader::Info &info, BufferView view, size_t idx) {
|
||||||
if (!view) // Return a dummy buffer if the constant buffer isn't bound
|
if (!view) // Return a dummy buffer if the constant buffer isn't bound
|
||||||
return BufferBinding{ctx.executor.AcquireMegaBufferAllocator().Allocate(ctx.executor.cycle, 0).buffer, 0, PAGE_SIZE};
|
return BufferBinding{ctx.gpu.megaBufferAllocator.Allocate(ctx.executor.cycle, 0).buffer, 0, PAGE_SIZE};
|
||||||
|
|
||||||
ctx.executor.AttachBuffer(view);
|
ctx.executor.AttachBuffer(view);
|
||||||
|
|
||||||
size_t sizeOverride{std::min<size_t>(info.constant_buffer_used_sizes[idx], view.size)};
|
size_t sizeOverride{std::min<size_t>(info.constant_buffer_used_sizes[idx], view.size)};
|
||||||
if (auto megaBufferBinding{view.TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber, sizeOverride)}) {
|
if (auto megaBufferBinding{view.TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionNumber, sizeOverride)}) {
|
||||||
return megaBufferBinding;
|
return megaBufferBinding;
|
||||||
} else {
|
} else {
|
||||||
view.GetBuffer()->BlockSequencedCpuBackingWrites();
|
view.GetBuffer()->BlockSequencedCpuBackingWrites();
|
||||||
@ -645,7 +645,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
if (desc.is_written) {
|
if (desc.is_written) {
|
||||||
view.GetBuffer()->MarkGpuDirty();
|
view.GetBuffer()->MarkGpuDirty();
|
||||||
} else {
|
} else {
|
||||||
if (auto megaBufferBinding{view.TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber)})
|
if (auto megaBufferBinding{view.TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionNumber)})
|
||||||
return megaBufferBinding;
|
return megaBufferBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
auto mappings{ctx.channelCtx.asCtx->gmmu.TranslateRange(textureHeader.Iova(), guest.GetSize())};
|
auto mappings{ctx.channelCtx.asCtx->gmmu.TranslateRange(textureHeader.Iova(), guest.GetSize())};
|
||||||
guest.mappings.assign(mappings.begin(), mappings.end());
|
guest.mappings.assign(mappings.begin(), mappings.end());
|
||||||
|
|
||||||
texture = ctx.executor.AcquireTextureManager().FindOrCreate(guest, ctx.executor.tag);
|
texture = ctx.gpu.texture.FindOrCreate(guest, ctx.executor.tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
textureHeaderCache[index] = {textureHeader, texture.get(), ctx.executor.executionNumber};
|
textureHeaderCache[index] = {textureHeader, texture.get(), ctx.executor.executionNumber};
|
||||||
|
@ -49,18 +49,6 @@ namespace skyline::gpu {
|
|||||||
|
|
||||||
MegaBufferAllocator::MegaBufferAllocator(GPU &gpu) : gpu{gpu}, activeChunk{chunks.emplace(chunks.end(), gpu)} {}
|
MegaBufferAllocator::MegaBufferAllocator(GPU &gpu) : gpu{gpu}, activeChunk{chunks.emplace(chunks.end(), gpu)} {}
|
||||||
|
|
||||||
void MegaBufferAllocator::lock() {
|
|
||||||
mutex.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MegaBufferAllocator::unlock() {
|
|
||||||
mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MegaBufferAllocator::try_lock() {
|
|
||||||
return mutex.try_lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
MegaBufferAllocator::Allocation MegaBufferAllocator::Allocate(const std::shared_ptr<FenceCycle> &cycle, vk::DeviceSize size, bool pageAlign) {
|
MegaBufferAllocator::Allocation MegaBufferAllocator::Allocate(const std::shared_ptr<FenceCycle> &cycle, vk::DeviceSize size, bool pageAlign) {
|
||||||
if (auto allocation{activeChunk->Allocate(cycle, size, pageAlign)}; allocation.first)
|
if (auto allocation{activeChunk->Allocate(cycle, size, pageAlign)}; allocation.first)
|
||||||
return {activeChunk->GetBacking(), allocation.first, allocation.second};
|
return {activeChunk->GetBacking(), allocation.first, allocation.second};
|
||||||
|
@ -40,7 +40,6 @@ namespace skyline::gpu {
|
|||||||
class MegaBufferAllocator {
|
class MegaBufferAllocator {
|
||||||
private:
|
private:
|
||||||
GPU &gpu;
|
GPU &gpu;
|
||||||
std::mutex mutex;
|
|
||||||
std::list<MegaBufferChunk> chunks; //!< A pool of all allocated megabuffer chunks, these are dynamically utilized
|
std::list<MegaBufferChunk> chunks; //!< A pool of all allocated megabuffer chunks, these are dynamically utilized
|
||||||
decltype(chunks)::iterator activeChunk; //!< Currently active chunk of the megabuffer which is being allocated into
|
decltype(chunks)::iterator activeChunk; //!< Currently active chunk of the megabuffer which is being allocated into
|
||||||
|
|
||||||
@ -60,24 +59,6 @@ namespace skyline::gpu {
|
|||||||
|
|
||||||
MegaBufferAllocator(GPU &gpu);
|
MegaBufferAllocator(GPU &gpu);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Acquires an exclusive lock on the allocator for the calling thread
|
|
||||||
* @note Naming is in accordance to the BasicLockable named requirement
|
|
||||||
*/
|
|
||||||
void lock();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Relinquishes an existing lock on the allocator by the calling thread
|
|
||||||
* @note Naming is in accordance to the BasicLockable named requirement
|
|
||||||
*/
|
|
||||||
void unlock();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Attempts to acquire an exclusive lock but returns immediately if it's captured by another thread
|
|
||||||
* @note Naming is in accordance to the Lockable named requirement
|
|
||||||
*/
|
|
||||||
bool try_lock();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Allocates data in a megabuffer chunk and returns an structure describing the allocation
|
* @brief Allocates data in a megabuffer chunk and returns an structure describing the allocation
|
||||||
* @param pageAlign Whether the pushed data should be page aligned in the megabuffer
|
* @param pageAlign Whether the pushed data should be page aligned in the megabuffer
|
||||||
|
@ -97,6 +97,8 @@ namespace skyline::gpu {
|
|||||||
frame.fence.Wait(state.soc->host1x);
|
frame.fence.Wait(state.soc->host1x);
|
||||||
|
|
||||||
std::scoped_lock textureLock(*frame.textureView);
|
std::scoped_lock textureLock(*frame.textureView);
|
||||||
|
// std::this_thread::sleep_for(std::chrono::milliseconds(64));
|
||||||
|
|
||||||
auto texture{frame.textureView->texture};
|
auto texture{frame.textureView->texture};
|
||||||
if (frame.textureView->format != swapchainFormat || texture->dimensions != swapchainExtent)
|
if (frame.textureView->format != swapchainFormat || texture->dimensions != swapchainExtent)
|
||||||
UpdateSwapchain(frame.textureView->format, texture->dimensions);
|
UpdateSwapchain(frame.textureView->format, texture->dimensions);
|
||||||
|
@ -6,18 +6,6 @@
|
|||||||
namespace skyline::gpu {
|
namespace skyline::gpu {
|
||||||
TextureManager::TextureManager(GPU &gpu) : gpu(gpu) {}
|
TextureManager::TextureManager(GPU &gpu) : gpu(gpu) {}
|
||||||
|
|
||||||
void TextureManager::lock() {
|
|
||||||
mutex.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextureManager::unlock() {
|
|
||||||
mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureManager::try_lock() {
|
|
||||||
return mutex.try_lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<TextureView> TextureManager::FindOrCreate(const GuestTexture &guestTexture, ContextTag tag) {
|
std::shared_ptr<TextureView> TextureManager::FindOrCreate(const GuestTexture &guestTexture, ContextTag tag) {
|
||||||
auto guestMapping{guestTexture.mappings.front()};
|
auto guestMapping{guestTexture.mappings.front()};
|
||||||
|
|
||||||
|
@ -26,30 +26,11 @@ namespace skyline::gpu {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GPU &gpu;
|
GPU &gpu;
|
||||||
std::mutex mutex; //!< Synchronizes access to the texture mappings
|
|
||||||
std::vector<TextureMapping> textures; //!< A sorted vector of all texture mappings
|
std::vector<TextureMapping> textures; //!< A sorted vector of all texture mappings
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TextureManager(GPU &gpu);
|
TextureManager(GPU &gpu);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Acquires an exclusive lock on the texture for the calling thread
|
|
||||||
* @note Naming is in accordance to the BasicLockable named requirement
|
|
||||||
*/
|
|
||||||
void lock();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Relinquishes an existing lock on the texture by the calling thread
|
|
||||||
* @note Naming is in accordance to the BasicLockable named requirement
|
|
||||||
*/
|
|
||||||
void unlock();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Attempts to acquire an exclusive lock but returns immediately if it's captured by another thread
|
|
||||||
* @note Naming is in accordance to the Lockable named requirement
|
|
||||||
*/
|
|
||||||
bool try_lock();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A pre-existing or newly created Texture object which matches the specified criteria
|
* @return A pre-existing or newly created Texture object which matches the specified criteria
|
||||||
* @note The texture manager **must** be locked prior to calling this
|
* @note The texture manager **must** be locked prior to calling this
|
||||||
|
@ -345,7 +345,7 @@ namespace skyline::service::hosbinder {
|
|||||||
gpu::GuestTexture guestTexture(span<u8>{}, dimensions, format, tileConfig, vk::ImageViewType::e2D);
|
gpu::GuestTexture guestTexture(span<u8>{}, dimensions, format, tileConfig, vk::ImageViewType::e2D);
|
||||||
guestTexture.mappings[0] = span<u8>(nvMapHandleObj->GetPointer() + surface.offset, guestTexture.GetLayerStride());
|
guestTexture.mappings[0] = span<u8>(nvMapHandleObj->GetPointer() + surface.offset, guestTexture.GetLayerStride());
|
||||||
|
|
||||||
std::scoped_lock textureLock{state.gpu->texture};
|
std::scoped_lock channelLock{state.gpu->channelLock};
|
||||||
buffer.texture = state.gpu->texture.FindOrCreate(guestTexture);
|
buffer.texture = state.gpu->texture.FindOrCreate(guestTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user