Copy source and update descriptor table
- mashroom33
- Topic Author
Less
More
1 month 2 weeks ago - 1 month 2 weeks ago #1
by mashroom33
Copy source and update descriptor table was created by mashroom33
I attempted to process the result of the previous draw in the game and then apply it to the subsequent draw. First, I created a new resource, and then copied the original resource to the new one via copy_texture_region. After that, I intended to replace the resource in the subsequent draw by updating the descriptor table, but I found that nothing happened.
Some key code:
copy source and create SRV:
resource res;
resource view srv;
resource_view_desc srvDesc = {};
resource_desc desc = origindesc;
desc.texture.width = (desc.texture.width +1)/2;
desc.heap = memory_heap::gpu_only;
desc.usage = resource_usage::copy_dest | resource_usage::shader_resource | resource_usage::render_target | resource_usage::copy_source;
cmd_list->barrier(originalres, resource_usage::shader_resource_pixel, resource_usage::copy_source);
cmd_list->barrier(res, resource_usage::general, resource_usage::copy_dest);
for (uint32_t level = 0;level < origindesc.texture.levels; ++level)
{
uint32t mipWidth = std::max(1u, desc.texture.width >> level);
uint32_t mipHeight = std::max(1u, desc.texture.height >> level);
subresource_box box={};
box.left=0;
box.top =0;
box.front =0;
box.right = (mipWidth +1)/2;
box.bottom = mipHeight;
box.back =1;
cmd_list->copy_texture_region(originalres, level, &sourceBoxLeft, res, level, nullptr, filter_mode::min_mag_mip_point);
}
cmd_list->barrier(res, resource_usage::copy_dest, resource_usage::general);
cmd_list->barrier(originalres, resource_usage::copy_source, resource_usage::shader resource_pixel);
resource_view_desc srvDesc = 0;
srvDesc.type = resource_view_type::texture_2d;
srvDesc.format = originaldesc.texture.format;
srvDesc.texture.first_level = 0;
srvDesc.texture.level_count = originaldesc.texture.levels;
srvDesc.texture.first_layer = 0;
srvDesc.texture.layer_count = 1;
device->create_resource_view(res, resource_usage::shader_resource, srvDesc, &srv)
In draw:
descriptor_table_update update ={};
update.type = descriptor_type::shader_resource_view;
update.table = repl.table;
update.binding = repl.binding;
update.array_offset = 0;
update.count =1;
update.descriptors = &srv;
if (update.table.handle != 0 && update.descriptors != nullptr)
{
commandList->get_device()->update_descriptor_tables(1, &update);
}
Some key code:
copy source and create SRV:
resource res;
resource view srv;
resource_view_desc srvDesc = {};
resource_desc desc = origindesc;
desc.texture.width = (desc.texture.width +1)/2;
desc.heap = memory_heap::gpu_only;
desc.usage = resource_usage::copy_dest | resource_usage::shader_resource | resource_usage::render_target | resource_usage::copy_source;
cmd_list->barrier(originalres, resource_usage::shader_resource_pixel, resource_usage::copy_source);
cmd_list->barrier(res, resource_usage::general, resource_usage::copy_dest);
for (uint32_t level = 0;level < origindesc.texture.levels; ++level)
{
uint32t mipWidth = std::max(1u, desc.texture.width >> level);
uint32_t mipHeight = std::max(1u, desc.texture.height >> level);
subresource_box box={};
box.left=0;
box.top =0;
box.front =0;
box.right = (mipWidth +1)/2;
box.bottom = mipHeight;
box.back =1;
cmd_list->copy_texture_region(originalres, level, &sourceBoxLeft, res, level, nullptr, filter_mode::min_mag_mip_point);
}
cmd_list->barrier(res, resource_usage::copy_dest, resource_usage::general);
cmd_list->barrier(originalres, resource_usage::copy_source, resource_usage::shader resource_pixel);
resource_view_desc srvDesc = 0;
srvDesc.type = resource_view_type::texture_2d;
srvDesc.format = originaldesc.texture.format;
srvDesc.texture.first_level = 0;
srvDesc.texture.level_count = originaldesc.texture.levels;
srvDesc.texture.first_layer = 0;
srvDesc.texture.layer_count = 1;
device->create_resource_view(res, resource_usage::shader_resource, srvDesc, &srv)
In draw:
descriptor_table_update update ={};
update.type = descriptor_type::shader_resource_view;
update.table = repl.table;
update.binding = repl.binding;
update.array_offset = 0;
update.count =1;
update.descriptors = &srv;
if (update.table.handle != 0 && update.descriptors != nullptr)
{
commandList->get_device()->update_descriptor_tables(1, &update);
}
Last edit: 1 month 2 weeks ago by mashroom33.
Please Log in or Create an account to join the conversation.
- crosire
Less
More
1 month 2 days ago #2
by crosire
Replied by crosire on topic Copy source and update descriptor table
What's the underlying graphics API of the game you are trying with?
The code as is seems reasonable (as long as "update_descriptor_tables" there is not actually invoked on every single draw, that would introduce a lot of overhead). Where is the descriptor table coming from that you are updating, are you sure it's actually used by the game? There may be other things at play, e.g. descriptor could be overwritten again by the game afterwards.
The code as is seems reasonable (as long as "update_descriptor_tables" there is not actually invoked on every single draw, that would introduce a lot of overhead). Where is the descriptor table coming from that you are updating, are you sure it's actually used by the game? There may be other things at play, e.g. descriptor could be overwritten again by the game afterwards.
Please Log in or Create an account to join the conversation.
- mashroom33
- Topic Author
Less
More
2 weeks 6 days ago #3
by mashroom33
Replied by mashroom33 on topic Copy source and update descriptor table
Sorry for the late reply. I have solved this problem. It was the incorrect setting of update.binding. Now we are facing another issue, as you said, we encountered problems when updating the descriptor:
Copy Descriptor A //update texture A in slot1
Draw A
Copy Descriptor B //update texture B in the same slot1
Draw B
Flush
At this point, we realize that DrawA will draw textureB. In summary, we need to replace the original texture, draw it once, then immediately replace the texture at the same position with another one and draw it again. How should we handle this situation?
Copy Descriptor A //update texture A in slot1
Draw A
Copy Descriptor B //update texture B in the same slot1
Draw B
Flush
At this point, we realize that DrawA will draw textureB. In summary, we need to replace the original texture, draw it once, then immediately replace the texture at the same position with another one and draw it again. How should we handle this situation?
Please Log in or Create an account to join the conversation.
- mashroom33
- Topic Author
Less
More
2 weeks 5 days ago #4
by mashroom33
Replied by mashroom33 on topic Copy source and update descriptor table
Forget to say~ I am using DX12
Please Log in or Create an account to join the conversation.
- crosire
Less
More
2 weeks 12 hours ago - 1 week 5 days ago #5
by crosire
Replied by crosire on topic Copy source and update descriptor table
That cannot be solved with a single descriptor table, each draw referencing different items would need its own table. So would need to allocate additional ones and clone all other entries over, then bind those.
Unfortunately this is rather finicky in D3D12, because the descriptor tables from the game and those created through device::allocate_descriptor_tables will be from different descriptor heaps, and only tables from a single heap may be bound in D3D12, which may impose problems (would really have to clone all descriptor tables that are bound, so that they are all from the same heap; ReShade will then switch descriptor heaps when binding the new descriptor tables automatically).
Unfortunately this is rather finicky in D3D12, because the descriptor tables from the game and those created through device::allocate_descriptor_tables will be from different descriptor heaps, and only tables from a single heap may be bound in D3D12, which may impose problems (would really have to clone all descriptor tables that are bound, so that they are all from the same heap; ReShade will then switch descriptor heaps when binding the new descriptor tables automatically).
Last edit: 1 week 5 days ago by crosire.
Please Log in or Create an account to join the conversation.
- mashroom33
- Topic Author
Less
More
1 week 5 days ago #6
by mashroom33
Replied by mashroom33 on topic Copy source and update descriptor table
Thank you for your answer! This is consistent with our recent test results.
We found that although we only need to update SRV, CBV also needs to be copied together, otherwise, the display will be incorrect.
But we also found that the sampler does not seem to need to be copied together. Could this be because in D3D12_DESCRIPTOR_HEAP_TYPE, CBV and SRV belong to the same type: D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, while the sampler is an independent type: D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER?
We found that although we only need to update SRV, CBV also needs to be copied together, otherwise, the display will be incorrect.
But we also found that the sampler does not seem to need to be copied together. Could this be because in D3D12_DESCRIPTOR_HEAP_TYPE, CBV and SRV belong to the same type: D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, while the sampler is an independent type: D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER?
Please Log in or Create an account to join the conversation.
- crosire
Less
More
1 week 5 days ago - 1 week 5 days ago #7
by crosire
Replied by crosire on topic Copy source and update descriptor table
Correct, there are two unique heaps that can be bound simultaneously in D3D12, one for CBVs, SRVs and UAVs and one for samplers (see
learn.microsoft.com/en-us/windows/win32/...t-setdescriptorheaps
, which ReShade calls internally as part of "command_list::bind_descriptor_tables" after detecting which heaps the passed descriptor tables were allocated from). So any descriptor tables containing samplers are independent from any descriptor tables containing CBVs, SRVs or UAVs. But as such any descriptor tables containing CBVs, SRVs or UAVs need to be from the same heap to be able to bind them together. And any descriptor tables containing samplers also need to be from the same heap of their own.
Last edit: 1 week 5 days ago by crosire.
Please Log in or Create an account to join the conversation.