Fix #142097: Vulkan: Crash with unbound textures
On the Vulkan side, ensure that unbound textures don't result in accessing uninitialized or out of bounds memory. On the Draw side, ensure all Hair and Curves attributes have, at least, a dummy attribute bound. Pull Request: https://projects.blender.org/blender/blender/pulls/142265
This commit is contained in:
@@ -301,13 +301,21 @@ gpu::Batch *curves_sub_pass_setup_implementation(PassT &sub_ps,
|
||||
CurvesEvalCache *curves_cache = drw_curves_cache_get(
|
||||
curves_id, gpu_material, subdiv, thickness_res);
|
||||
|
||||
/* Fix issue with certain driver not drawing anything if there is nothing bound to
|
||||
* "ac", "au", "u" or "c". */
|
||||
/* Ensure we have no unbound resources.
|
||||
* Required for Vulkan.
|
||||
* Fixes issues with certain GL drivers not drawing anything. */
|
||||
sub_ps.bind_texture("u", module.dummy_vbo);
|
||||
sub_ps.bind_texture("au", module.dummy_vbo);
|
||||
sub_ps.bind_texture("a", module.dummy_vbo);
|
||||
sub_ps.bind_texture("c", module.dummy_vbo);
|
||||
sub_ps.bind_texture("ac", module.dummy_vbo);
|
||||
sub_ps.bind_texture("a", module.dummy_vbo);
|
||||
if (gpu_material) {
|
||||
ListBase attr_list = GPU_material_attributes(gpu_material);
|
||||
ListBaseWrapper<GPUMaterialAttribute> attrs(attr_list);
|
||||
for (const GPUMaterialAttribute *attr : attrs) {
|
||||
sub_ps.bind_texture(attr->input_name, module.dummy_vbo);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Generalize radius implementation for curves data type. */
|
||||
float hair_rad_shape = 0.0f;
|
||||
|
||||
@@ -178,6 +178,25 @@ blender::gpu::Batch *hair_sub_pass_setup_implementation(PassT &sub_ps,
|
||||
ParticleHairCache *hair_cache = drw_hair_particle_cache_get(
|
||||
object, psys, md, gpu_material, subdiv, thickness_res);
|
||||
|
||||
/* TODO(fclem): Remove Global access. */
|
||||
CurvesModule &module = *drw_get().data->curves_module;
|
||||
|
||||
/* Ensure we have no unbound resources.
|
||||
* Required for Vulkan.
|
||||
* Fixes issues with certain GL drivers not drawing anything. */
|
||||
sub_ps.bind_texture("u", module.dummy_vbo);
|
||||
sub_ps.bind_texture("au", module.dummy_vbo);
|
||||
sub_ps.bind_texture("a", module.dummy_vbo);
|
||||
sub_ps.bind_texture("c", module.dummy_vbo);
|
||||
sub_ps.bind_texture("ac", module.dummy_vbo);
|
||||
if (gpu_material) {
|
||||
ListBase attr_list = GPU_material_attributes(gpu_material);
|
||||
ListBaseWrapper<GPUMaterialAttribute> attrs(attr_list);
|
||||
for (const GPUMaterialAttribute *attr : attrs) {
|
||||
sub_ps.bind_texture(attr->input_name, module.dummy_vbo);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: optimize this. Only bind the ones #GPUMaterial needs. */
|
||||
for (int i : IndexRange(hair_cache->num_uv_layers)) {
|
||||
for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->uv_layer_names[i][n][0] != '\0'; n++) {
|
||||
@@ -190,21 +209,6 @@ blender::gpu::Batch *hair_sub_pass_setup_implementation(PassT &sub_ps,
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO(fclem): Remove Global access. */
|
||||
CurvesModule &module = *drw_get().data->curves_module;
|
||||
|
||||
/* Fix issue with certain driver not drawing anything if there is nothing bound to
|
||||
* "ac", "au", "u" or "c". */
|
||||
if (hair_cache->num_uv_layers == 0) {
|
||||
sub_ps.bind_texture("u", module.dummy_vbo);
|
||||
sub_ps.bind_texture("au", module.dummy_vbo);
|
||||
sub_ps.bind_texture("a", module.dummy_vbo);
|
||||
}
|
||||
if (hair_cache->num_col_layers == 0) {
|
||||
sub_ps.bind_texture("c", module.dummy_vbo);
|
||||
sub_ps.bind_texture("ac", module.dummy_vbo);
|
||||
}
|
||||
|
||||
float4x4 dupli_mat = ob_ref.particles_matrix();
|
||||
|
||||
/* Get hair shape parameters. */
|
||||
|
||||
@@ -92,7 +92,13 @@ void VKDescriptorSetUpdator::bind_texture_resource(const VKDevice &device,
|
||||
const VKResourceBinding &resource_binding,
|
||||
render_graph::VKResourceAccessInfo &access_info)
|
||||
{
|
||||
const BindSpaceTextures::Elem &elem = state_manager.textures_.get(resource_binding.binding);
|
||||
const BindSpaceTextures::Elem *elem_ptr = state_manager.textures_.get(resource_binding.binding);
|
||||
if (!elem_ptr) {
|
||||
/* Unbound resource. */
|
||||
BLI_assert_unreachable();
|
||||
return;
|
||||
}
|
||||
const BindSpaceTextures::Elem &elem = *elem_ptr;
|
||||
switch (elem.resource_type) {
|
||||
case BindSpaceTextures::Type::VertexBuffer: {
|
||||
VKVertexBuffer &vertex_buffer = *static_cast<VKVertexBuffer *>(elem.resource);
|
||||
@@ -162,7 +168,14 @@ void VKDescriptorSetUpdator::bind_input_attachment_resource(
|
||||
}
|
||||
else {
|
||||
bool supports_dynamic_rendering = device.extensions_get().dynamic_rendering;
|
||||
const BindSpaceTextures::Elem &elem = state_manager.textures_.get(resource_binding.binding);
|
||||
const BindSpaceTextures::Elem *elem_ptr = state_manager.textures_.get(
|
||||
resource_binding.binding);
|
||||
if (!elem_ptr) {
|
||||
/* Unbound resource. */
|
||||
BLI_assert_unreachable();
|
||||
return;
|
||||
}
|
||||
const BindSpaceTextures::Elem &elem = *elem_ptr;
|
||||
VKTexture *texture = static_cast<VKTexture *>(elem.resource);
|
||||
BLI_assert(texture);
|
||||
BLI_assert(elem.resource_type == BindSpaceTextures::Type::Texture);
|
||||
|
||||
@@ -174,16 +174,22 @@ class BindSpaceTextures {
|
||||
void bind(Type resource_type, void *resource, GPUSamplerState sampler, int binding)
|
||||
{
|
||||
if (bound_resources.size() <= binding) {
|
||||
bound_resources.resize(binding + 1);
|
||||
bound_resources.resize(binding + 1, {});
|
||||
}
|
||||
bound_resources[binding].resource_type = resource_type;
|
||||
bound_resources[binding].resource = resource;
|
||||
bound_resources[binding].sampler = sampler;
|
||||
}
|
||||
|
||||
const Elem &get(int binding) const
|
||||
const Elem *get(int binding) const
|
||||
{
|
||||
return bound_resources[binding];
|
||||
if (binding >= bound_resources.size()) {
|
||||
/* TODO: Check with @Jeroen-Bakker.
|
||||
* Could we ensure state_manager adds default initialized bindings for each ShaderInterface
|
||||
* resource? (See #142097). */
|
||||
return nullptr;
|
||||
}
|
||||
return &bound_resources[binding];
|
||||
}
|
||||
|
||||
void unbind(void *resource)
|
||||
|
||||
Reference in New Issue
Block a user