Add workaround for Vulkan pipeline compilation errors on Adreno 660.
This commit is contained in:
@@ -717,6 +717,13 @@ void RenderingDeviceDriverVulkan::_check_driver_workarounds(const VkPhysicalDevi
|
||||
p_device_properties.driverVersion < VK_MAKE_VERSION(512, 503, 0) &&
|
||||
strstr(p_device_properties.deviceName, "Turnip") == nullptr;
|
||||
|
||||
// Don't print pipeline compilation errors on Adreno 660, as they are expected to happen on this device with ubershaders.
|
||||
// Unhandled error cases will still pop up elsewhere in RD. (eg. when attempting to bind an invalid pipeline.)
|
||||
driver_workarounds.dont_print_on_render_pipeline_creation_failure =
|
||||
p_device_properties.vendorID == RenderingContextDriver::Vendor::VENDOR_QUALCOMM &&
|
||||
p_device_properties.deviceID == 0x6060001 && // Adreno 660
|
||||
strstr(p_device_properties.deviceName, "Turnip") == nullptr;
|
||||
|
||||
// Workaround a driver bug on Adreno 730 GPUs that keeps leaking memory on each call to vkResetDescriptorPool.
|
||||
// Which eventually run out of memory. In such case we should not be using linear allocated pools
|
||||
// Bug introduced in driver 512.597.0 and fixed in 512.671.0.
|
||||
@@ -6216,6 +6223,12 @@ RDD::PipelineID RenderingDeviceDriverVulkan::render_pipeline_create(
|
||||
|
||||
VkPipeline vk_pipeline = VK_NULL_HANDLE;
|
||||
VkResult err = vkCreateGraphicsPipelines(vk_device, pipelines_cache.vk_cache, 1, &pipeline_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_PIPELINE), &vk_pipeline);
|
||||
|
||||
// Don't print error for VK_ERROR_UNKNOWN on Adreno 660.
|
||||
if (unlikely(err == VK_ERROR_UNKNOWN && driver_workarounds.dont_print_on_render_pipeline_creation_failure)) {
|
||||
return PipelineID();
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V_MSG(err, PipelineID(), vformat("Couldn't create Vulkan graphics pipelines (VkResult error %d).", err));
|
||||
|
||||
#if RECORD_PIPELINE_STATISTICS
|
||||
|
||||
@@ -2564,7 +2564,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
|
||||
RID pipeline_rd;
|
||||
RID vertex_array_rd;
|
||||
RID index_array_rd;
|
||||
const uint32_t ubershader_iterations = (disable_ubershaders ? 1 : 2);
|
||||
uint32_t ubershader_iterations = (disable_ubershaders ? 1 : 2);
|
||||
bool pipeline_valid = false;
|
||||
while (pipeline_key.ubershader < ubershader_iterations) {
|
||||
// Skeleton and blend shape.
|
||||
@@ -2589,7 +2589,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
|
||||
|
||||
if (shader != prev_shader || pipeline_hash != prev_pipeline_hash) {
|
||||
RSE::PipelineSource pipeline_source = pipeline_key.ubershader ? RSE::PIPELINE_SOURCE_DRAW : RSE::PIPELINE_SOURCE_SPECIALIZATION;
|
||||
pipeline_rd = shader->pipeline_hash_map.get_pipeline(pipeline_key, pipeline_hash, pipeline_key.ubershader || disable_ubershaders, pipeline_source);
|
||||
pipeline_rd = shader->pipeline_hash_map.get_pipeline(pipeline_key, pipeline_hash, pipeline_key.ubershader == (ubershader_iterations - 1), pipeline_source);
|
||||
|
||||
if (pipeline_rd.is_valid()) {
|
||||
pipeline_valid = true;
|
||||
@@ -2597,7 +2597,14 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
|
||||
prev_pipeline_hash = pipeline_hash;
|
||||
break;
|
||||
} else {
|
||||
pipeline_key.ubershader++;
|
||||
if (pipeline_key.ubershader == 1) {
|
||||
// If ubershader failed to compile, retry specialized shader and wait for it to finish compilation.
|
||||
// This prevents pop-in at the cost of shader compilation stutters.
|
||||
pipeline_key.ubershader = 0;
|
||||
ubershader_iterations = 1;
|
||||
} else {
|
||||
pipeline_key.ubershader++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The same pipeline is bound already.
|
||||
|
||||
@@ -448,6 +448,12 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
|
||||
ERR_FAIL_COND(shader_rid.is_null());
|
||||
|
||||
RID pipeline = RD::get_singleton()->render_pipeline_create(shader_rid, p_pipeline_key.framebuffer_format_id, p_pipeline_key.vertex_format_id, primitive_rd, raster_state, multisample_state, depth_stencil_state, blend_state, 0, p_pipeline_key.render_pass, specialization_constants);
|
||||
|
||||
// Don't print error when it's expected.
|
||||
if (unlikely(pipeline.is_null() && RD::get_singleton()->get_driver_workarounds().dont_print_on_render_pipeline_creation_failure)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(pipeline.is_null());
|
||||
|
||||
pipeline_hash_map.add_compiled_pipeline(p_pipeline_key.hash(), pipeline);
|
||||
|
||||
@@ -4951,6 +4951,12 @@ RID RenderingDevice::render_pipeline_create(RID p_shader, FramebufferFormatID p_
|
||||
fb_format.render_pass,
|
||||
p_for_render_pass,
|
||||
p_specialization_constants);
|
||||
|
||||
// Don't print error when it's expected.
|
||||
if (unlikely(!pipeline.driver_id && driver->get_driver_workarounds().dont_print_on_render_pipeline_creation_failure)) {
|
||||
return RID();
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(!pipeline.driver_id, RID());
|
||||
|
||||
if (pipeline_cache_enabled) {
|
||||
|
||||
@@ -1052,6 +1052,7 @@ public:
|
||||
// Driver workarounds that require higher level code and cannot be solely implemented in RenderingDeviceDriver.
|
||||
struct DriverWorkarounds {
|
||||
bool avoid_compute_after_draw = false;
|
||||
bool dont_print_on_render_pipeline_creation_failure = false;
|
||||
bool disable_ubershaders = false;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user