mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-28 09:55:29 +03:00
Split out common parts of Maxwell 3D draws
These will be able to be shared between indirect and normal draws.
This commit is contained in:
parent
779ba3de05
commit
d5b6c68ae4
@ -112,6 +112,80 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
return scissor;
|
return scissor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::Rect2D Maxwell3D::GetDrawScissor() {
|
||||||
|
const auto &surfaceClip{clearEngineRegisters.surfaceClip};
|
||||||
|
vk::Rect2D scissor{{surfaceClip.horizontal.x, surfaceClip.vertical.y},
|
||||||
|
{surfaceClip.horizontal.width, surfaceClip.vertical.height}};
|
||||||
|
|
||||||
|
auto colorAttachments{activeState.GetColorAttachments()};
|
||||||
|
auto depthStencilAttachment{activeState.GetDepthAttachment()};
|
||||||
|
auto depthStencilAttachmentSpan{depthStencilAttachment ? span<TextureView *>(depthStencilAttachment) : span<TextureView *>()};
|
||||||
|
for (auto attachment : ranges::views::concat(colorAttachments, depthStencilAttachmentSpan)) {
|
||||||
|
if (attachment) {
|
||||||
|
scissor.extent.width = std::min(scissor.extent.width, static_cast<u32>(static_cast<i32>(attachment->texture->dimensions.width) - scissor.offset.x));
|
||||||
|
scissor.extent.height = std::min(scissor.extent.height, static_cast<u32>(static_cast<i32>(attachment->texture->dimensions.height) - scissor.offset.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return scissor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Maxwell3D::PrepareDraw(StateUpdateBuilder &builder,
|
||||||
|
engine::DrawTopology topology, bool indexed, bool estimateIndexBufferSize, u32 firstIndex, u32 count,
|
||||||
|
vk::PipelineStageFlags &srcStageMask, vk::PipelineStageFlags &dstStageMask) {
|
||||||
|
Pipeline *oldPipeline{activeState.GetPipeline()};
|
||||||
|
samplers.Update(ctx, samplerBinding.value == engine::SamplerBinding::Value::ViaHeaderBinding);
|
||||||
|
activeState.Update(ctx, textures, constantBuffers.boundConstantBuffers,
|
||||||
|
builder,
|
||||||
|
indexed, topology, estimateIndexBufferSize, firstIndex, count,
|
||||||
|
srcStageMask, dstStageMask);
|
||||||
|
Pipeline *pipeline{activeState.GetPipeline()};
|
||||||
|
activeDescriptorSetSampledImages.resize(pipeline->GetTotalSampledImageCount());
|
||||||
|
|
||||||
|
|
||||||
|
auto *descUpdateInfo{[&]() -> DescriptorUpdateInfo * {
|
||||||
|
if (((oldPipeline == pipeline) || (oldPipeline && oldPipeline->CheckBindingMatch(pipeline))) && constantBuffers.quickBindEnabled) {
|
||||||
|
// If bindings between the old and new pipelines are the same we can reuse the descriptor sets given that quick bind is enabled (meaning that no buffer updates or calls to non-graphics engines have occurred that could invalidate them)
|
||||||
|
if (constantBuffers.quickBind)
|
||||||
|
// If only a single constant buffer has been rebound between draws we can perform a partial descriptor update
|
||||||
|
return pipeline->SyncDescriptorsQuickBind(ctx, constantBuffers.boundConstantBuffers, samplers, textures,
|
||||||
|
*constantBuffers.quickBind, activeDescriptorSetSampledImages,
|
||||||
|
srcStageMask, dstStageMask);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
// If bindings have changed or quick bind is disabled, perform a full descriptor update
|
||||||
|
return pipeline->SyncDescriptors(ctx, constantBuffers.boundConstantBuffers, samplers, textures,
|
||||||
|
activeDescriptorSetSampledImages,
|
||||||
|
srcStageMask, dstStageMask);
|
||||||
|
}
|
||||||
|
}()};
|
||||||
|
|
||||||
|
if (oldPipeline != pipeline)
|
||||||
|
// If the pipeline has changed, we need to update the pipeline state
|
||||||
|
builder.SetPipeline(pipeline->compiledPipeline.pipeline, vk::PipelineBindPoint::eGraphics);
|
||||||
|
|
||||||
|
if (descUpdateInfo) {
|
||||||
|
if (ctx.gpu.traits.supportsPushDescriptors) {
|
||||||
|
builder.SetDescriptorSetWithPush(descUpdateInfo);
|
||||||
|
} else {
|
||||||
|
if (!attachedDescriptorSets)
|
||||||
|
attachedDescriptorSets = std::make_shared<boost::container::static_vector<DescriptorAllocator::ActiveDescriptorSet, DescriptorBatchSize>>();
|
||||||
|
|
||||||
|
auto newSet{&attachedDescriptorSets->emplace_back(ctx.gpu.descriptor.AllocateSet(descUpdateInfo->descriptorSetLayout))};
|
||||||
|
auto *oldSet{activeDescriptorSet};
|
||||||
|
activeDescriptorSet = newSet;
|
||||||
|
|
||||||
|
builder.SetDescriptorSetWithUpdate(descUpdateInfo, activeDescriptorSet, oldSet);
|
||||||
|
|
||||||
|
if (attachedDescriptorSets->size() == DescriptorBatchSize) {
|
||||||
|
ctx.executor.AttachDependency(attachedDescriptorSets);
|
||||||
|
attachedDescriptorSets.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Maxwell3D::LoadConstantBuffer(span<u32> data, u32 offset) {
|
void Maxwell3D::LoadConstantBuffer(span<u32> data, u32 offset) {
|
||||||
constantBuffers.Load(ctx, data, offset);
|
constantBuffers.Load(ctx, data, offset);
|
||||||
}
|
}
|
||||||
@ -222,9 +296,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
StateUpdateBuilder builder{*ctx.executor.allocator};
|
StateUpdateBuilder builder{*ctx.executor.allocator};
|
||||||
vk::PipelineStageFlags srcStageMask{}, dstStageMask{};
|
vk::PipelineStageFlags srcStageMask{}, dstStageMask{};
|
||||||
|
|
||||||
Pipeline *oldPipeline{activeState.GetPipeline()};
|
PrepareDraw(builder, topology, indexed, false, first, count, srcStageMask, dstStageMask);
|
||||||
samplers.Update(ctx, samplerBinding.value == engine::SamplerBinding::Value::ViaHeaderBinding);
|
|
||||||
activeState.Update(ctx, textures, constantBuffers.boundConstantBuffers, builder, indexed, topology, first, count, srcStageMask, dstStageMask);
|
|
||||||
if (directState.inputAssembly.NeedsQuadConversion()) {
|
if (directState.inputAssembly.NeedsQuadConversion()) {
|
||||||
count = conversion::quads::GetIndexCount(count);
|
count = conversion::quads::GetIndexCount(count);
|
||||||
first = 0;
|
first = 0;
|
||||||
@ -237,48 +310,6 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pipeline *pipeline{activeState.GetPipeline()};
|
|
||||||
activeDescriptorSetSampledImages.resize(pipeline->GetTotalSampledImageCount());
|
|
||||||
|
|
||||||
|
|
||||||
auto *descUpdateInfo{[&]() -> DescriptorUpdateInfo * {
|
|
||||||
if (((oldPipeline == pipeline) || (oldPipeline && oldPipeline->CheckBindingMatch(pipeline))) && constantBuffers.quickBindEnabled) {
|
|
||||||
// If bindings between the old and new pipelines are the same we can reuse the descriptor sets given that quick bind is enabled (meaning that no buffer updates or calls to non-graphics engines have occurred that could invalidate them)
|
|
||||||
if (constantBuffers.quickBind)
|
|
||||||
// If only a single constant buffer has been rebound between draws we can perform a partial descriptor update
|
|
||||||
return pipeline->SyncDescriptorsQuickBind(ctx, constantBuffers.boundConstantBuffers, samplers, textures, *constantBuffers.quickBind, activeDescriptorSetSampledImages, srcStageMask, dstStageMask);
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
} else {
|
|
||||||
// If bindings have changed or quick bind is disabled, perform a full descriptor update
|
|
||||||
return pipeline->SyncDescriptors(ctx, constantBuffers.boundConstantBuffers, samplers, textures, activeDescriptorSetSampledImages, srcStageMask, dstStageMask);
|
|
||||||
}
|
|
||||||
}()};
|
|
||||||
|
|
||||||
if (oldPipeline != pipeline)
|
|
||||||
// If the pipeline has changed, we need to update the pipeline state
|
|
||||||
builder.SetPipeline(pipeline->compiledPipeline.pipeline, vk::PipelineBindPoint::eGraphics);
|
|
||||||
|
|
||||||
if (descUpdateInfo) {
|
|
||||||
if (ctx.gpu.traits.supportsPushDescriptors) {
|
|
||||||
builder.SetDescriptorSetWithPush(descUpdateInfo);
|
|
||||||
} else {
|
|
||||||
if (!attachedDescriptorSets)
|
|
||||||
attachedDescriptorSets = std::make_shared<boost::container::static_vector<DescriptorAllocator::ActiveDescriptorSet, DescriptorBatchSize>>();
|
|
||||||
|
|
||||||
auto newSet{&attachedDescriptorSets->emplace_back(ctx.gpu.descriptor.AllocateSet(descUpdateInfo->descriptorSetLayout))};
|
|
||||||
auto *oldSet{activeDescriptorSet};
|
|
||||||
activeDescriptorSet = newSet;
|
|
||||||
|
|
||||||
builder.SetDescriptorSetWithUpdate(descUpdateInfo, activeDescriptorSet, oldSet);
|
|
||||||
|
|
||||||
if (attachedDescriptorSets->size() == DescriptorBatchSize) {
|
|
||||||
ctx.executor.AttachDependency(attachedDescriptorSets);
|
|
||||||
attachedDescriptorSets.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto stateUpdater{builder.Build()};
|
auto stateUpdater{builder.Build()};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -298,24 +329,10 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
count, first, instanceCount, vertexOffset, firstInstance, indexed,
|
count, first, instanceCount, vertexOffset, firstInstance, indexed,
|
||||||
ctx.gpu.traits.supportsTransformFeedback ? transformFeedbackEnable : false})};
|
ctx.gpu.traits.supportsTransformFeedback ? transformFeedbackEnable : false})};
|
||||||
|
|
||||||
const auto &surfaceClip{clearEngineRegisters.surfaceClip};
|
vk::Rect2D scissor{GetDrawScissor()};
|
||||||
vk::Rect2D scissor{
|
|
||||||
{surfaceClip.horizontal.x, surfaceClip.vertical.y},
|
|
||||||
{surfaceClip.horizontal.width, surfaceClip.vertical.height}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto colorAttachments{activeState.GetColorAttachments()};
|
|
||||||
auto depthStencilAttachment{activeState.GetDepthAttachment()};
|
|
||||||
auto depthStencilAttachmentSpan{depthStencilAttachment ? span<TextureView *>(depthStencilAttachment) : span<TextureView *>()};
|
|
||||||
for (auto attachment : ranges::views::concat(colorAttachments, depthStencilAttachmentSpan)) {
|
|
||||||
if (attachment) {
|
|
||||||
scissor.extent.width = std::min(scissor.extent.width, static_cast<u32>(static_cast<i32>(attachment->texture->dimensions.width) - scissor.offset.x));
|
|
||||||
scissor.extent.height = std::min(scissor.extent.height, static_cast<u32>(static_cast<i32>(attachment->texture->dimensions.height) - scissor.offset.y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constantBuffers.ResetQuickBind();
|
constantBuffers.ResetQuickBind();
|
||||||
|
|
||||||
ctx.executor.AddSubpass([drawParams](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &, GPU &gpu, vk::RenderPass, u32) {
|
ctx.executor.AddSubpass([drawParams](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &, GPU &gpu, vk::RenderPass, u32) {
|
||||||
drawParams->stateUpdater.RecordAll(gpu, commandBuffer);
|
drawParams->stateUpdater.RecordAll(gpu, commandBuffer);
|
||||||
|
|
||||||
|
@ -57,8 +57,23 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
|
|
||||||
size_t UpdateQuadConversionBuffer(u32 count, u32 firstVertex);
|
size_t UpdateQuadConversionBuffer(u32 count, u32 firstVertex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A scissor derived from the current clear register state
|
||||||
|
*/
|
||||||
vk::Rect2D GetClearScissor();
|
vk::Rect2D GetClearScissor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A scissor derived from the current draw register state and bound RTs
|
||||||
|
*/
|
||||||
|
vk::Rect2D GetDrawScissor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Performs operations common across indirect and regular draws
|
||||||
|
*/
|
||||||
|
void PrepareDraw(StateUpdateBuilder &builder,
|
||||||
|
engine::DrawTopology topology, bool indexed, bool estimateIndexBufferSize, u32 firstIndex, u32 count,
|
||||||
|
vk::PipelineStageFlags &srcStageMask, vk::PipelineStageFlags &dstStageMask);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DirectPipelineState &directState;
|
DirectPipelineState &directState;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user