Does https://github.com/doitsujin/vkd3d/tree/srv-frog work around the problem?
Note that this isn't a proper fix, but more of quick attempt to figure out what the issue is. I don't have the game installed to check locally at the moment.
That is rather surprising since 8-bit structured buffer does not exist in D3D12, but could be game bug ...
Does https://github.com/doitsujin/vkd3d/tree/srv-frog work around the problem?
Note that this isn't a proper fix, but more of quick attempt to figure out what the issue is. I don't have the game installed to check locally at the moment.
Yes, it does. The game launches and I can spot 2 frogs in the logs.
$ cat steam-2531310.log | grep frog
3090271.496:0150:0154:err:vkd3d-proton:vkd3d_structured_srv_to_texel_buffer_dxgi_format: frog
3090271.496:0150:0154:err:vkd3d-proton:vkd3d_structured_uav_to_texel_buffer_dxgi_format: frog
I'll be happy to test more stuff or provide more data if you need.
Thanks!
I have read through the previous comments and the proposed fix. Just one additional note.The crash is triggered along the following path:
d3d12_device_CreateShaderResourceView_embedded → d3d12_desc_create_srv_embedded → vkd3d_create_buffer_srv_embedded.
Under normal conditions, when the game passes a valid VK_FORMAT_R16_UINT, the function vkd3d_get_metadata_buffer_view_for_resource correctly computes view->range = 2. Everything works as expected. However, if the game passes a specific set of parameters — likely a game-side bug — the following edge case occurs:
desc->Format = DXGI_FORMAT_UNKNOWN
desc->Buffer.NumElements = 1
desc->Buffer.StructureByteStride = 1
desc->Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE
isl_genX(buffer_fill_state_s)(const struct isl_device *dev, void *state,
const struct isl_buffer_fill_state_info *restrict info)
{
uint64_t buffer_size = info->size_B;
.......
uint64_t num_elements = buffer_size / info->stride_B;
assert(num_elements > 0);
s.Height = ((num_elements - 1) >> 7) & 0x3fff;
s.Width = (num_elements - 1) & 0x7f;
s.Depth = ((num_elements - 1) >> 21) & 0x7ff;
}
In a Mesa debug build, assert(num_elements > 0) fires and terminates the game application. In a release build, the assertion is compiled out. The code proceeds with num_elements == 0, which produces incorrect values for Height, Width, and Depth written to the hardware surface state registers. This can lead to rendering corruption, screen artifacts, or other subtle GPU misbehaviour. As the proposed fix suggests, this is about handling the edge case of range = 1.
I tested the updated tree and it seems to work for me. That was fast! Thanks a lot, everybody!
Hi
When running The Last Of Us Part II Remastered with the Mesa Anv driver in debug mode, we're hitting an assertion regarding num_elements because vkGetDescriptorEXT() is passing a range of 1 for an R16 descriptor:
It seems that if the app passed
range = 0, it would be violatingVUID-VkDescriptorAddressInfoEXT-range-08940, but I can't find text that says "half a pixel" is invalid. Anv roundsrangedown to "whole pixels", which transforms it into 0, so we hit the assertion in the ISL code.I'm not sure how much this is on purpose, or expected, so, before removing the assertion in Anv, I'd like to have your assessment here. Is this a vkd3d bug? Is this a Game bug?
This may be related somehow to https://github.com/HansKristian-Work/vkd3d-proton/issues/2071 ?
Thanks a lot!