mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 20:41:50 +01:00
Add a fast binding sync path for when only one cbuf has changed
SMO implements instanced draws by repeating the same draw just with a different constant buffer bound. Reduce the cost of this significantly by detecting such cases and instead of processing every descriptor, copy the previous descriptor set and update only the ones affected by the bound constant buffer. Credits to ripinperiperi for the initial idea and making me aware of how SMO does these draws
This commit is contained in:
parent
89edd9b303
commit
7b4da52445
@ -80,9 +80,24 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
void ConstantBuffers::Bind(InterconnectContext &ctx, engine::ShaderStage stage, size_t index) {
|
void ConstantBuffers::Bind(InterconnectContext &ctx, engine::ShaderStage stage, size_t index) {
|
||||||
auto &view{*selectorState.UpdateGet(ctx).view};
|
auto &view{*selectorState.UpdateGet(ctx).view};
|
||||||
boundConstantBuffers[static_cast<size_t>(stage)][index] = {view};
|
boundConstantBuffers[static_cast<size_t>(stage)][index] = {view};
|
||||||
|
|
||||||
|
if (quickBindEnabled && quickBind)
|
||||||
|
DisableQuickBind(); // We can only quick bind one buffer per draw
|
||||||
|
else if (quickBindEnabled)
|
||||||
|
quickBind = QuickBind{index, stage};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantBuffers::Unbind(engine::ShaderStage stage, size_t index) {
|
void ConstantBuffers::Unbind(engine::ShaderStage stage, size_t index) {
|
||||||
boundConstantBuffers[static_cast<size_t>(stage)][index] = {};
|
boundConstantBuffers[static_cast<size_t>(stage)][index] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConstantBuffers::ResetQuickBind() {
|
||||||
|
quickBindEnabled = true;
|
||||||
|
quickBind.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConstantBuffers::DisableQuickBind() {
|
||||||
|
quickBindEnabled = false;
|
||||||
|
quickBind.reset();
|
||||||
|
}
|
||||||
}
|
}
|
@ -52,6 +52,16 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
public:
|
public:
|
||||||
ConstantBufferSet boundConstantBuffers;
|
ConstantBufferSet boundConstantBuffers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allows for a single constant buffer to be bound between two draws without requiring a full descriptor sync
|
||||||
|
*/
|
||||||
|
struct QuickBind {
|
||||||
|
size_t index; //!< The index of the constant buffer to bind
|
||||||
|
engine::ShaderStage stage; //!< The shader stage to bind the constant buffer to
|
||||||
|
};
|
||||||
|
std::optional<QuickBind> quickBind;
|
||||||
|
bool quickBindEnabled{}; //!< If quick binding can occur, if multiple bindings, constant buffer loads or other engines have been used since the last draw this is disabled
|
||||||
|
|
||||||
ConstantBuffers(DirtyManager &manager, const ConstantBufferSelectorState::EngineRegisters &constantBufferSelectorRegisters);
|
ConstantBuffers(DirtyManager &manager, const ConstantBufferSelectorState::EngineRegisters &constantBufferSelectorRegisters);
|
||||||
|
|
||||||
void MarkAllDirty();
|
void MarkAllDirty();
|
||||||
@ -61,5 +71,15 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
void Bind(InterconnectContext &ctx, engine::ShaderStage stage, size_t index);
|
void Bind(InterconnectContext &ctx, engine::ShaderStage stage, size_t index);
|
||||||
|
|
||||||
void Unbind(engine::ShaderStage stage, size_t index);
|
void Unbind(engine::ShaderStage stage, size_t index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resets quick binding state to be ready store a new bind, this should be called after every draw
|
||||||
|
*/
|
||||||
|
void ResetQuickBind();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Diables quick binding, this should be called before any operation that could impact contents of bound constant buffers
|
||||||
|
*/
|
||||||
|
void DisableQuickBind();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,10 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
constantBuffers.Unbind(stage, index);
|
constantBuffers.Unbind(stage, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Maxwell3D::DisableQuickConstantBufferBind() {
|
||||||
|
constantBuffers.DisableQuickBind();
|
||||||
|
}
|
||||||
|
|
||||||
void Maxwell3D::Clear(engine::ClearSurface &clearSurface) {
|
void Maxwell3D::Clear(engine::ClearSurface &clearSurface) {
|
||||||
auto scissor{GetClearScissor()};
|
auto scissor{GetClearScissor()};
|
||||||
if (scissor.extent.width == 0 || scissor.extent.height == 0)
|
if (scissor.extent.width == 0 || scissor.extent.height == 0)
|
||||||
|
@ -62,6 +62,11 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
*/
|
*/
|
||||||
void BindConstantBuffer(engine::ShaderStage stage, u32 index, bool enable);
|
void BindConstantBuffer(engine::ShaderStage stage, u32 index, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @note See ConstantBuffers::DisableQuickBind
|
||||||
|
*/
|
||||||
|
void DisableQuickConstantBufferBind();
|
||||||
|
|
||||||
void Clear(engine::ClearSurface &clearSurface);
|
void Clear(engine::ClearSurface &clearSurface);
|
||||||
|
|
||||||
void Draw(engine::DrawTopology topology, bool indexed, u32 count, u32 first, u32 instanceCount, u32 vertexOffset, u32 firstInstance);
|
void Draw(engine::DrawTopology topology, bool indexed, u32 count, u32 first, u32 instanceCount, u32 vertexOffset, u32 firstInstance);
|
||||||
|
@ -221,16 +221,22 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
Pipeline::DescriptorInfo descriptorInfo{};
|
Pipeline::DescriptorInfo descriptorInfo{};
|
||||||
u32 bindingIndex{};
|
u32 bindingIndex{};
|
||||||
|
|
||||||
for (const auto &stage : shaderStages) {
|
for (size_t i{}; i < engine::ShaderStageCount; i++) {
|
||||||
|
const auto &stage{shaderStages[i]};
|
||||||
if (!stage.module)
|
if (!stage.module)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto pushBindings{[&](vk::DescriptorType type, const auto &descs, u32 &count, bool individualDescWrites = false) {
|
auto &stageCbufUsage{descriptorInfo.cbufUsages[i]};
|
||||||
|
|
||||||
|
auto pushBindings{[&](vk::DescriptorType type, const auto &descs, u32 &count, auto &&descCb, bool individualDescWrites = false) {
|
||||||
descriptorInfo.writeDescCount += individualDescWrites ? descs.size() : ((descs.size() > 0) ? 1 : 0);
|
descriptorInfo.writeDescCount += individualDescWrites ? descs.size() : ((descs.size() > 0) ? 1 : 0);
|
||||||
|
|
||||||
for (const auto &desc : descs) {
|
for (u32 descIdx{}; descIdx < descs.size(); descIdx++) {
|
||||||
|
const auto &desc{descs[descIdx]};
|
||||||
count += desc.count;
|
count += desc.count;
|
||||||
|
|
||||||
|
descCb(desc, descIdx);
|
||||||
|
|
||||||
descriptorInfo.descriptorSetLayoutBindings.push_back(vk::DescriptorSetLayoutBinding{
|
descriptorInfo.descriptorSetLayoutBindings.push_back(vk::DescriptorSetLayoutBinding{
|
||||||
.binding = bindingIndex++,
|
.binding = bindingIndex++,
|
||||||
.descriptorType = type,
|
.descriptorType = type,
|
||||||
@ -240,19 +246,32 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
pushBindings(vk::DescriptorType::eUniformBuffer, stage.info.constant_buffer_descriptors, descriptorInfo.uniformBufferDescCount);
|
pushBindings(vk::DescriptorType::eUniformBuffer, stage.info.constant_buffer_descriptors, descriptorInfo.uniformBufferDescCount, [&](const Shader::ConstantBufferDescriptor &desc, u32 descIdx) {
|
||||||
pushBindings(vk::DescriptorType::eStorageBuffer, stage.info.storage_buffers_descriptors, descriptorInfo.storageBufferDescCount);
|
for (u32 cbufIdx{desc.index}; cbufIdx < desc.index + desc.count; cbufIdx++) {
|
||||||
|
auto &usage{stageCbufUsage[cbufIdx]};
|
||||||
|
usage.uniformBuffers.push_back({bindingIndex, descIdx});
|
||||||
|
usage.totalBufferDescCount += desc.count;
|
||||||
|
usage.writeDescCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pushBindings(vk::DescriptorType::eStorageBuffer, stage.info.storage_buffers_descriptors, descriptorInfo.storageBufferDescCount, [&](const Shader::StorageBufferDescriptor &desc, u32 descIdx) {
|
||||||
|
auto &usage{stageCbufUsage[desc.cbuf_index]};
|
||||||
|
usage.storageBuffers.push_back({bindingIndex, descIdx});
|
||||||
|
usage.totalBufferDescCount += desc.count;
|
||||||
|
usage.writeDescCount++;
|
||||||
|
});
|
||||||
descriptorInfo.totalBufferDescCount += descriptorInfo.uniformBufferDescCount + descriptorInfo.storageBufferDescCount;
|
descriptorInfo.totalBufferDescCount += descriptorInfo.uniformBufferDescCount + descriptorInfo.storageBufferDescCount;
|
||||||
|
|
||||||
pushBindings(vk::DescriptorType::eUniformTexelBuffer, stage.info.texture_buffer_descriptors, descriptorInfo.uniformTexelBufferDescCount);
|
pushBindings(vk::DescriptorType::eUniformTexelBuffer, stage.info.texture_buffer_descriptors, descriptorInfo.uniformTexelBufferDescCount, [](const auto &, u32) {});
|
||||||
pushBindings(vk::DescriptorType::eStorageTexelBuffer, stage.info.image_buffer_descriptors, descriptorInfo.storageTexelBufferDescCount);
|
pushBindings(vk::DescriptorType::eStorageTexelBuffer, stage.info.image_buffer_descriptors, descriptorInfo.storageTexelBufferDescCount, [](const auto &, u32) {});
|
||||||
descriptorInfo.totalTexelBufferDescCount += descriptorInfo.uniformTexelBufferDescCount + descriptorInfo.storageTexelBufferDescCount;
|
descriptorInfo.totalTexelBufferDescCount += descriptorInfo.uniformTexelBufferDescCount + descriptorInfo.storageTexelBufferDescCount;
|
||||||
|
|
||||||
pushBindings(vk::DescriptorType::eCombinedImageSampler, stage.info.texture_descriptors, descriptorInfo.combinedImageSamplerDescCount, needsIndividualTextureBindingWrites);
|
pushBindings(vk::DescriptorType::eCombinedImageSampler, stage.info.texture_descriptors, descriptorInfo.combinedImageSamplerDescCount, [](const auto &, u32) {}, needsIndividualTextureBindingWrites);
|
||||||
pushBindings(vk::DescriptorType::eStorageImage, stage.info.image_descriptors, descriptorInfo.storageImageDescCount);
|
pushBindings(vk::DescriptorType::eStorageImage, stage.info.image_descriptors, descriptorInfo.storageImageDescCount, [](const auto &, u32) {});
|
||||||
descriptorInfo.totalImageDescCount += descriptorInfo.combinedImageSamplerDescCount + descriptorInfo.storageImageDescCount;
|
descriptorInfo.totalImageDescCount += descriptorInfo.combinedImageSamplerDescCount + descriptorInfo.storageImageDescCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
descriptorInfo.totalElemCount = descriptorInfo.totalBufferDescCount + descriptorInfo.totalTexelBufferDescCount + descriptorInfo.totalImageDescCount;
|
||||||
return descriptorInfo;
|
return descriptorInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,6 +561,38 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
transitionCacheNextIdx = (transitionCacheNextIdx + 1) % transitionCache.size();
|
transitionCacheNextIdx = (transitionCacheNextIdx + 1) % transitionCache.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DynamicBufferBinding GetConstantBufferBinding(InterconnectContext &ctx, const Shader::Info &info, BufferView view, size_t idx) {
|
||||||
|
ctx.executor.AttachBuffer(view);
|
||||||
|
|
||||||
|
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)}) {
|
||||||
|
return megaBufferBinding;
|
||||||
|
} else {
|
||||||
|
view.GetBuffer()->BlockSequencedCpuBackingWrites();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DynamicBufferBinding GetStorageBufferBinding(InterconnectContext &ctx, const Shader::Info &info, ConstantBuffer &cbuf, CachedMappedBufferView &cachedView, size_t idx) {
|
||||||
|
struct SsboDescriptor {
|
||||||
|
u64 address;
|
||||||
|
u32 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto &desc{info.storage_buffers_descriptors[idx]};
|
||||||
|
auto ssbo{cbuf.Read<SsboDescriptor>(ctx.executor, desc.cbuf_offset)};
|
||||||
|
cachedView.Update(ctx, ssbo.address, ssbo.size);
|
||||||
|
|
||||||
|
auto view{cachedView.view};
|
||||||
|
ctx.executor.AttachBuffer(view);
|
||||||
|
view.GetBuffer()->BlockSequencedCpuBackingWrites();
|
||||||
|
|
||||||
|
if (desc.is_written)
|
||||||
|
view.GetBuffer()->MarkGpuDirty();
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: EXEC ID FOR STORAGE BUFS PURGE REMAP
|
// TODO: EXEC ID FOR STORAGE BUFS PURGE REMAP
|
||||||
void Pipeline::SyncDescriptors(InterconnectContext &ctx, ConstantBufferSet &constantBuffers) {
|
void Pipeline::SyncDescriptors(InterconnectContext &ctx, ConstantBufferSet &constantBuffers) {
|
||||||
u32 bindingIdx{};
|
u32 bindingIdx{};
|
||||||
@ -572,41 +623,69 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
|
|
||||||
for (size_t i{}; i < shaderStages.size(); i++) {
|
for (size_t i{}; i < shaderStages.size(); i++) {
|
||||||
const auto &stage{shaderStages[i]};
|
const auto &stage{shaderStages[i]};
|
||||||
|
if (!stage.module)
|
||||||
|
continue;
|
||||||
|
|
||||||
writeBufferDescs(vk::DescriptorType::eUniformBuffer, stage.info.constant_buffer_descriptors, descriptorInfo.uniformBufferDescCount,
|
writeBufferDescs(vk::DescriptorType::eUniformBuffer, stage.info.constant_buffer_descriptors, descriptorInfo.uniformBufferDescCount,
|
||||||
[&](const Shader::ConstantBufferDescriptor &desc, size_t descIdx, size_t arrayIdx) -> DynamicBufferBinding {
|
[&](const Shader::ConstantBufferDescriptor &desc, size_t descIdx, size_t arrayIdx) {
|
||||||
size_t cbufIdx{desc.index + arrayIdx};
|
size_t cbufIdx{desc.index + arrayIdx};
|
||||||
auto view{constantBuffers[i][cbufIdx].view};
|
return GetConstantBufferBinding(ctx, stage.info, constantBuffers[i][cbufIdx].view, cbufIdx);
|
||||||
|
|
||||||
ctx.executor.AttachBuffer(view);
|
|
||||||
|
|
||||||
size_t sizeOverride{std::min<size_t>(stage.info.constant_buffer_used_sizes[cbufIdx], view.size)};
|
|
||||||
if (auto megaBufferBinding{view.TryMegaBuffer(ctx.executor.cycle, ctx.executor.AcquireMegaBufferAllocator(), ctx.executor.executionNumber, sizeOverride)}) {
|
|
||||||
return megaBufferBinding;
|
|
||||||
} else {
|
|
||||||
view.GetBuffer()->BlockSequencedCpuBackingWrites();
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
writeBufferDescs(vk::DescriptorType::eStorageBuffer, stage.info.storage_buffers_descriptors, descriptorInfo.storageBufferDescCount, [&](const Shader::StorageBufferDescriptor &desc, size_t descIdx, size_t arrayIdx) {
|
writeBufferDescs(vk::DescriptorType::eStorageBuffer, stage.info.storage_buffers_descriptors, descriptorInfo.storageBufferDescCount,
|
||||||
struct SsboDescriptor {
|
[&](const Shader::StorageBufferDescriptor &desc, size_t descIdx, size_t arrayIdx) {
|
||||||
u64 address;
|
return GetStorageBufferBinding(ctx, stage.info, constantBuffers[i][desc.cbuf_index], storageBufferViews[descIdx], descIdx);
|
||||||
u32 size;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto &cbuf{constantBuffers[i][desc.cbuf_index]};
|
|
||||||
auto ssbo{cbuf.Read<SsboDescriptor>(ctx.executor, desc.cbuf_offset)};
|
|
||||||
storageBufferViews[descIdx].Update(ctx, ssbo.address, ssbo.size);
|
|
||||||
|
|
||||||
auto view{storageBufferViews[descIdx].view};
|
|
||||||
ctx.executor.AttachBuffer(view);
|
|
||||||
|
|
||||||
if (desc.is_written)
|
|
||||||
view.GetBuffer()->MarkGpuDirty();
|
|
||||||
|
|
||||||
return view;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Pipeline::SyncDescriptorsQuickBind(InterconnectContext &ctx, ConstantBufferSet &constantBuffers, ConstantBuffers::QuickBind quickBind) {
|
||||||
|
const auto &cbufUsageInfo{descriptorInfo.cbufUsages[static_cast<size_t>(quickBind.stage)][quickBind.index]};
|
||||||
|
const auto &shaderInfo{shaderStages[static_cast<size_t>(quickBind.stage)].info};
|
||||||
|
auto &stageConstantBuffers{constantBuffers[static_cast<size_t>(quickBind.stage)]};
|
||||||
|
auto copy{ctx.executor.allocator.AllocateUntracked<vk::CopyDescriptorSet>()};
|
||||||
|
auto writes{ctx.executor.allocator.AllocateUntracked<vk::WriteDescriptorSet>(cbufUsageInfo.writeDescCount)};
|
||||||
|
size_t writeIdx{};
|
||||||
|
size_t bufferIdx{};
|
||||||
|
|
||||||
|
auto bufferDescs{ctx.executor.allocator.AllocateUntracked<vk::DescriptorBufferInfo>(cbufUsageInfo.totalBufferDescCount)};
|
||||||
|
auto bufferDescViews{ctx.executor.allocator.AllocateUntracked<DynamicBufferBinding>(cbufUsageInfo.totalBufferDescCount)};
|
||||||
|
|
||||||
|
// TODO: opt this to do partial copy
|
||||||
|
*copy = vk::CopyDescriptorSet{
|
||||||
|
.srcBinding = 0,
|
||||||
|
.srcArrayElement = 0,
|
||||||
|
.dstBinding = 0,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = descriptorInfo.totalElemCount,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto writeBufferDescs{[&](vk::DescriptorType type, const auto &usages, const auto &descs, u32 count, auto getBufferCb) {
|
||||||
|
for (const auto &usage : usages) {
|
||||||
|
const auto &shaderDesc{descs[usage.shaderDescIdx]};
|
||||||
|
|
||||||
|
writes[writeIdx++] = {
|
||||||
|
.dstBinding = usage.binding,
|
||||||
|
.descriptorCount = shaderDesc.count,
|
||||||
|
.descriptorType = type,
|
||||||
|
.pBufferInfo = &bufferDescs[bufferIdx],
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i{}; i < shaderDesc.count; i++)
|
||||||
|
bufferDescViews[bufferIdx++] = getBufferCb(shaderDesc, usage.shaderDescIdx, i);
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
writeBufferDescs(vk::DescriptorType::eUniformBuffer, cbufUsageInfo.uniformBuffers, shaderInfo.constant_buffer_descriptors, descriptorInfo.uniformBufferDescCount,
|
||||||
|
[&](const Shader::ConstantBufferDescriptor &desc, size_t descIdx, size_t arrayIdx) -> DynamicBufferBinding {
|
||||||
|
size_t cbufIdx{desc.index + arrayIdx};
|
||||||
|
return GetConstantBufferBinding(ctx, shaderInfo, stageConstantBuffers[cbufIdx].view, cbufIdx);
|
||||||
|
});
|
||||||
|
|
||||||
|
writeBufferDescs(vk::DescriptorType::eStorageBuffer, cbufUsageInfo.storageBuffers, shaderInfo.storage_buffers_descriptors, descriptorInfo.storageBufferDescCount,
|
||||||
|
[&](const Shader::StorageBufferDescriptor &desc, size_t descIdx, size_t arrayIdx) {
|
||||||
|
return GetStorageBufferBinding(ctx, shaderInfo, stageConstantBuffers[desc.cbuf_index], storageBufferViews[bufferIdx], descIdx);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,24 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
u32 combinedImageSamplerDescCount{};
|
u32 combinedImageSamplerDescCount{};
|
||||||
u32 storageImageDescCount{};
|
u32 storageImageDescCount{};
|
||||||
u32 totalImageDescCount{};
|
u32 totalImageDescCount{};
|
||||||
|
u32 totalElemCount{};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Keeps track of all bindings that are dependent on a given constant buffer index to allow for quick binding
|
||||||
|
*/
|
||||||
|
struct ConstantBufferDescriptorUsages {
|
||||||
|
struct Usage {
|
||||||
|
u32 binding; //!< Vulkan binding index
|
||||||
|
u32 shaderDescIdx; //!< Index of the descriptor in the appropriate shader info member
|
||||||
|
};
|
||||||
|
|
||||||
|
boost::container::small_vector<Usage, 2> uniformBuffers;
|
||||||
|
boost::container::small_vector<Usage, 2> storageBuffers;
|
||||||
|
u32 totalBufferDescCount{};
|
||||||
|
u32 writeDescCount{};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<std::array<ConstantBufferDescriptorUsages, engine::ShaderStageConstantBufferCount>, engine::ShaderStageCount> cbufUsages{};
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -61,6 +79,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
void AddTransition(Pipeline *next);
|
void AddTransition(Pipeline *next);
|
||||||
|
|
||||||
void SyncDescriptors(InterconnectContext &ctx, ConstantBufferSet &constantBuffers);
|
void SyncDescriptors(InterconnectContext &ctx, ConstantBufferSet &constantBuffers);
|
||||||
|
|
||||||
|
void SyncDescriptorsQuickBind(InterconnectContext &ctx, ConstantBufferSet &constantBuffers, ConstantBuffers::QuickBind quickBind);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PipelineManager {
|
class PipelineManager {
|
||||||
|
@ -107,6 +107,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
#undef LOAD_CONSTANT_BUFFER_CALLBACKS
|
#undef LOAD_CONSTANT_BUFFER_CALLBACKS
|
||||||
default:
|
default:
|
||||||
// When a method other than constant buffer update is called submit our submit the previously built-up update as a batch
|
// When a method other than constant buffer update is called submit our submit the previously built-up update as a batch
|
||||||
|
interconnect.DisableQuickConstantBufferBind();
|
||||||
interconnect.LoadConstantBuffer(batchLoadConstantBuffer.buffer, batchLoadConstantBuffer.Invalidate());
|
interconnect.LoadConstantBuffer(batchLoadConstantBuffer.buffer, batchLoadConstantBuffer.Invalidate());
|
||||||
batchLoadConstantBuffer.Reset();
|
batchLoadConstantBuffer.Reset();
|
||||||
break; // Continue on here to handle the actual method
|
break; // Continue on here to handle the actual method
|
||||||
@ -177,6 +178,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ENGINE_STRUCT_CASE(i2m, launchDma, {
|
ENGINE_STRUCT_CASE(i2m, launchDma, {
|
||||||
|
FlushEngineState();
|
||||||
i2m.LaunchDma(*registers.i2m);
|
i2m.LaunchDma(*registers.i2m);
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -258,7 +260,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
|
|
||||||
#define PIPELINE_CALLBACKS(z, idx, data) \
|
#define PIPELINE_CALLBACKS(z, idx, data) \
|
||||||
ENGINE_ARRAY_STRUCT_CASE(bindGroups, idx, constantBuffer, { \
|
ENGINE_ARRAY_STRUCT_CASE(bindGroups, idx, constantBuffer, { \
|
||||||
interconnect.BindConstantBuffer(static_cast<type::ShaderStage>(idx), constantBuffer.shaderSlot, constantBuffer.valid); \
|
interconnect.BindConstantBuffer(static_cast<type::ShaderStage>(idx), constantBuffer.shaderSlot, constantBuffer.valid); \
|
||||||
})
|
})
|
||||||
|
|
||||||
BOOST_PP_REPEAT(5, PIPELINE_CALLBACKS, 0)
|
BOOST_PP_REPEAT(5, PIPELINE_CALLBACKS, 0)
|
||||||
@ -297,6 +299,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
interconnect.LoadConstantBuffer(batchLoadConstantBuffer.buffer, batchLoadConstantBuffer.Invalidate());
|
interconnect.LoadConstantBuffer(batchLoadConstantBuffer.buffer, batchLoadConstantBuffer.Invalidate());
|
||||||
batchLoadConstantBuffer.Reset();
|
batchLoadConstantBuffer.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interconnect.DisableQuickConstantBufferBind();
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline)) void Maxwell3D::CallMethod(u32 method, u32 argument) {
|
__attribute__((always_inline)) void Maxwell3D::CallMethod(u32 method, u32 argument) {
|
||||||
|
Loading…
Reference in New Issue
Block a user