-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
base: main
Are you sure you want to change the base?
Conversation
0f1de27
to
80a3519
Compare
5979024
to
6353291
Compare
1fe426e
to
ec90035
Compare
ec90035
to
3264e1d
Compare
2c066d9
to
79a7528
Compare
62da111
to
391cbcf
Compare
5900c24
to
5404f8a
Compare
the per-view descriptor-set layout depends on both the material and the variant.
2282c08
to
9c46dcc
Compare
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()) { |
There was a problem hiding this comment.
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.
No description provided.