skyline/app/src/main/cpp/skyline/gpu/interconnect/common/pipeline.inc

120 lines
5.7 KiB
C++

// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <gpu/interconnect/command_executor.h>
#include "samplers.h"
#include "textures.h"
namespace skyline::gpu::interconnect {
union BindlessHandle {
u32 raw;
struct {
u32 textureIndex : 20;
u32 samplerIndex : 12;
};
};
static DynamicBufferBinding GetConstantBufferBinding(InterconnectContext &ctx,
span<const u32, Shader::Info::MAX_CBUFS> cbufSizes,
BufferView view, size_t idx,
vk::PipelineStageFlagBits dstStage,
vk::PipelineStageFlags &srcStageMask, vk::PipelineStageFlags &dstStageMask) {
if (!view) // Return a dummy buffer if the constant buffer isn't bound
return BufferBinding{ctx.gpu.megaBufferAllocator.Allocate(ctx.executor.cycle, PAGE_SIZE).buffer, 0, PAGE_SIZE};
ctx.executor.AttachBuffer(view);
view.GetBuffer()->PopulateReadBarrier(dstStage, srcStageMask, dstStageMask);
size_t sizeOverride{std::min<size_t>(cbufSizes[idx], view.size)};
if (auto megaBufferBinding{view.TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionTag, sizeOverride)}) {
return megaBufferBinding;
} else {
view.GetBuffer()->BlockSequencedCpuBackingWrites();
return view;
}
}
static DynamicBufferBinding GetStorageBufferBinding(InterconnectContext &ctx, const auto &desc,
ConstantBuffer &cbuf, CachedMappedBufferView &cachedView,
vk::PipelineStageFlagBits dstStage,
vk::PipelineStageFlags &srcStageMask, vk::PipelineStageFlags &dstStageMask) {
struct SsboDescriptor {
u64 address;
u32 size;
};
auto ssbo{cbuf.Read<SsboDescriptor>(ctx.executor, desc.cbuf_offset)};
if (ssbo.size == 0)
return BufferBinding{ctx.gpu.megaBufferAllocator.Allocate(ctx.executor.cycle, PAGE_SIZE).buffer, 0, PAGE_SIZE};
size_t padding{ssbo.address & (ctx.gpu.traits.minimumStorageBufferAlignment - 1)};
cachedView.Update(ctx, ssbo.address - padding, util::AlignUp(ssbo.size + padding, ctx.gpu.traits.minimumStorageBufferAlignment));
if (!cachedView.view) // Return a dummy buffer if the SSBO isn't bound
return BufferBinding{ctx.gpu.megaBufferAllocator.Allocate(ctx.executor.cycle, PAGE_SIZE).buffer, 0, PAGE_SIZE};
auto view{cachedView.view};
ctx.executor.AttachBuffer(view);
view.GetBuffer()->PopulateReadBarrier(dstStage, srcStageMask, dstStageMask);
if (desc.is_written) {
if (view.GetBuffer()->SequencedCpuBackingWritesBlocked()) {
srcStageMask |= vk::PipelineStageFlagBits::eAllCommands;
dstStageMask |= dstStage;
}
view.GetBuffer()->MarkGpuDirty(ctx.executor.usageTracker);
} else {
if (auto megaBufferBinding{view.TryMegaBuffer(ctx.executor.cycle, ctx.gpu.megaBufferAllocator, ctx.executor.executionTag)})
return megaBufferBinding;
}
view.GetBuffer()->BlockSequencedCpuBackingWrites();
return view;
}
static BindlessHandle ReadBindlessHandle(InterconnectContext &ctx, auto &constantBuffers, const auto &desc, size_t arrayIdx) {
ConstantBuffer &primaryCbuf{constantBuffers[desc.cbuf_index]};
if (!primaryCbuf.view)
return { .raw = 0 };
size_t elemOffset{arrayIdx << desc.size_shift};
size_t primaryCbufOffset{desc.cbuf_offset + elemOffset};
u32 primaryVal{primaryCbuf.Read<u32>(ctx.executor, primaryCbufOffset)};
if constexpr (requires { desc.has_secondary; }) {
if (desc.has_secondary) {
ConstantBuffer &secondaryCbuf{constantBuffers[desc.secondary_cbuf_index]};
size_t secondaryCbufOffset{desc.secondary_cbuf_offset + elemOffset};
u32 secondaryVal{secondaryCbuf.Read<u32>(ctx.executor, secondaryCbufOffset)};
return {.raw = (primaryVal << desc.shift_left) | (secondaryVal << desc.secondary_shift_left)};
}
}
return {.raw = primaryVal};
}
static std::pair<vk::DescriptorImageInfo, TextureView *> GetTextureBinding(InterconnectContext &ctx, const auto &desc,
Samplers &samplers, Textures &textures,
BindlessHandle handle,
vk::PipelineStageFlagBits dstStage,
vk::PipelineStageFlags &srcStageMask, vk::PipelineStageFlags &dstStageMask) {
auto sampler{samplers.GetSampler(ctx, handle.samplerIndex, handle.textureIndex)};
auto texture{textures.GetTexture(ctx, handle.textureIndex, desc.type)};
ctx.executor.AttachTexture(texture);
auto view{texture->GetView()};
texture->texture->PopulateReadBarrier(dstStage, srcStageMask, dstStageMask);
return {
vk::DescriptorImageInfo{
.sampler = **sampler,
.imageView = view,
.imageLayout = texture->texture->layout
},
texture
};
}
}