Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: new descriptor set backend API #7737

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft

Conversation

pixelflinger
Copy link
Collaborator

No description provided.

@pixelflinger pixelflinger added the internal Issue/PR does not affect clients label Apr 4, 2024
Base automatically changed from ma/material-cleanup to main April 15, 2024 17:27
@pixelflinger pixelflinger force-pushed the ma/descriptor-sets branch 2 times, most recently from 5979024 to 6353291 Compare April 20, 2024 06:59
@pixelflinger pixelflinger force-pushed the ma/descriptor-sets branch 2 times, most recently from 1fe426e to ec90035 Compare May 3, 2024 19:51
@pixelflinger pixelflinger force-pushed the ma/descriptor-sets branch 2 times, most recently from 2c066d9 to 79a7528 Compare May 23, 2024 20:55
@pixelflinger pixelflinger force-pushed the ma/descriptor-sets branch 5 times, most recently from 62da111 to 391cbcf Compare May 30, 2024 22:19
@pixelflinger pixelflinger force-pushed the ma/descriptor-sets branch 5 times, most recently from 5900c24 to 5404f8a Compare June 7, 2024 18:19
Comment on lines +382 to +407
using iter_type = decltype(mHistory)::iterator;
std::array<iter_type, UNIQUE_DESCRIPTOR_SET_COUNT> iterators = {mHistory.end()};
bool allBound = true;

// Once bound, the resources are now ref'd in the descriptor set and the some resources can
// be released and the descriptor set is ref'd by the command buffer.
for (uint8_t i = 0; i < mSamplerMap.size(); ++i) {
auto const& [info, texture] = mSamplerMap[i];
if (texture) {
mResources.release(texture);
for (uint8_t i = 0; i < UNIQUE_DESCRIPTOR_SET_COUNT; ++i) {
if ((setMask & (1LL << i)) == 0) {
continue;
}
auto const vkset = mStashedSets[i];
if (auto itr = mHistory.find(vkset); itr != mHistory.end() && !itr->second.bound()) {
allBound = false;
iterators[i] = itr;
}
mSamplerMap[i] = {{}, nullptr};
}
mInputAttachment = {};
mHaveDynamicUbos = false;

FVK_SYSTRACE_END();
return pipelineLayout;
}

void dynamicBind(VulkanCommandBuffer* commands, Handle<VulkanDescriptorSetLayout> uboLayout) {
if (!mHaveDynamicUbos) {
BoundInfo nextInfo = {
pipelineLayout,
setMask,
mStashedSets,
};
if (allBound && mLastBoundInfo == nextInfo) {
return;
}
FVK_SYSTRACE_CONTEXT();
FVK_SYSTRACE_START("dynamic-bind");

assert_invariant(mBoundState.valid());
assert_invariant(commands->buffer() == mBoundState.cmdbuf);

auto layout = mAllocator->handle_cast<VulkanDescriptorSetLayout*>(
mBoundState.layouts[UBO_SET_ID]);

// Note that this is costly, instead just use dynamic UBOs with dynamic offsets.
auto const& [set, cached] = getSet(UBO_SET_ID, layout);
VkDescriptorSet const vkSet = set->vkSet;

if (!cached) {
VkWriteDescriptorSet descriptorWrites[MAX_UBO_BINDING];
uint8_t nwrites = 0;

for (uint8_t binding: layout->bindings.ubo) {
auto const& [info, ubo] = mUboMap[binding];
descriptorWrites[nwrites++] = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
.dstSet = vkSet,
.dstBinding = binding,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.pBufferInfo = ubo ? &info : &mPlaceHolderBufferInfo,
};
if (ubo) {
set->resources.acquire(ubo);
}
}
if (nwrites > 0) {
vkUpdateDescriptorSets(mDevice, nwrites, descriptorWrites, 0, nullptr);
}
}
commands->acquire(set);

if (mBoundState.vkSets[UBO_SET_ID] != vkSet) {
vkCmdBindDescriptorSets(mBoundState.cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS,
mBoundState.pipelineLayout, 0, 1, &vkSet, 0, nullptr);
mBoundState.vkSets[UBO_SET_ID] = vkSet;
for (uint8_t i = 0; i < UNIQUE_DESCRIPTOR_SET_COUNT; ++i) {
auto& itr = iterators[i];
if (itr != mHistory.end()) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems to me that all this code could be replaced by a 4 bits bitset with forEachBitSet(). All this does above is figure which of the 4 set needs a call to bind(), so this should just be 4 bits.

This code is part of the most inner loop we have, it should be optimized to death!

There should also be a fast path for "just changing the offsets". The way I did this in the gl backend is that I keep two sets of bitset and I can very quickly know which sets (1) don't change, (2) are only a bind offset update or (3) need a real rebind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
internal Issue/PR does not affect clients
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant