Browse Source

vulkan: Better handling for shader failing to load

rdb 2 years ago
parent
commit
7a0124f82e

+ 6 - 2
panda/src/vulkandisplay/vulkanGraphicsStateGuardian.cxx

@@ -2163,11 +2163,15 @@ set_state_and_transform(const RenderState *state,
   VulkanShaderContext *sc = _default_sc;
   Shader *shader = (Shader *)_target_shader->get_shader();
   if (shader != nullptr) {
-    DCAST_INTO_V(sc, shader->prepare_now(get_prepared_objects(), this));
+    sc = DCAST(VulkanShaderContext, shader->prepare_now(get_prepared_objects(), this));
   }
 
   _current_shader = sc;
-  nassertv(sc != nullptr);
+  if (UNLIKELY(sc == nullptr)) {
+    // Don't bother updating the state if we don't have a valid shader, because
+    // begin_draw_primitives will return false anyway.
+    return;
+  }
 
   // Put the modelview projection matrix and color scale in the push constants.
   if (sc->_projection_mat_stage_mask != 0) {

+ 25 - 4
panda/src/vulkandisplay/vulkanShaderContext.cxx

@@ -113,11 +113,23 @@ create_modules(VkDevice device, const ShaderType::Struct *push_constant_block_ty
     }
   }
 
+  bool success = true;
   for (Shader::LinkedModule &linked_module : _shader->_modules) {
     CPT(ShaderModule) module = linked_module._module.get_read_pointer();
+    nassertd(module != nullptr) {
+      success = false;
+      continue;
+    }
+
+    if (!module->is_of_type(ShaderModuleSpirV::get_class_type())) {
+      vulkandisplay_cat.error()
+        << "Shader modules of type " << module->get_type()
+        << " are not supported in Vulkan\n";
+      success = false;
+      continue;
+    }
 
-    const ShaderModuleSpirV *spv_module = DCAST(ShaderModuleSpirV, module.p());
-    nassertd(spv_module != nullptr) continue;
+    const ShaderModuleSpirV *spv_module = (const ShaderModuleSpirV *)module.p();
 
     // Make a clean copy, so we can do some transformations on it.
     ShaderModuleSpirV::InstructionStream instructions = spv_module->_instructions;
@@ -179,11 +191,20 @@ create_modules(VkDevice device, const ShaderType::Struct *push_constant_block_ty
     err = vkCreateShaderModule(device, &module_info, nullptr, &_modules[(size_t)spv_module->get_stage()]);
     if (err) {
       vulkan_error(err, "Failed to create shader modules");
-      return false;
+      success = false;
+    }
+  }
+
+  if (!success) {
+    for (size_t i = 0; i <= (size_t)Shader::Stage::compute; ++i) {
+      if (_modules[i] != VK_NULL_HANDLE) {
+        vkDestroyShaderModule(device, _modules[i], nullptr);
+        _modules[i] = VK_NULL_HANDLE;
+      }
     }
   }
 
-  return true;
+  return success;
 }
 
 /**