diff --git a/src/freedreno/vulkan/tu_device.cc b/src/freedreno/vulkan/tu_device.cc index c7910079abd..78849469f18 100644 --- a/src/freedreno/vulkan/tu_device.cc +++ b/src/freedreno/vulkan/tu_device.cc @@ -2184,6 +2184,12 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice, device->global_bo_map = global; tu_init_clear_blit_shaders(device); + result = tu_init_empty_shaders(device); + if (result != VK_SUCCESS) { + vk_startup_errorf(device->instance, result, "empty shaders"); + goto fail_empty_shaders; + } + global->predicate = 0; global->vtx_stats_query_not_running = 1; global->dbg_one = (uint32_t)-1; @@ -2327,6 +2333,8 @@ fail_perfcntrs_pass_alloc: fail_pipeline_cache: tu_destroy_dynamic_rendering(device); fail_dynamic_rendering: + tu_destroy_empty_shaders(device); +fail_empty_shaders: tu_destroy_clear_blit_shaders(device); fail_global_bo_map: tu_bo_finish(device, device->global_bo); @@ -2377,6 +2385,8 @@ tu_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator) tu_destroy_clear_blit_shaders(device); + tu_destroy_empty_shaders(device); + tu_destroy_dynamic_rendering(device); ir3_compiler_destroy(device->compiler); diff --git a/src/freedreno/vulkan/tu_device.h b/src/freedreno/vulkan/tu_device.h index f84734a3d42..286789af6e8 100644 --- a/src/freedreno/vulkan/tu_device.h +++ b/src/freedreno/vulkan/tu_device.h @@ -287,6 +287,8 @@ struct tu_device struct ir3_shader *global_shaders[GLOBAL_SH_COUNT]; uint64_t global_shader_va[GLOBAL_SH_COUNT]; + struct tu_shader *empty_tcs, *empty_tes, *empty_gs, *empty_fs; + uint32_t vsc_draw_strm_pitch; uint32_t vsc_prim_strm_pitch; BITSET_DECLARE(custom_border_color, TU_BORDER_COLOR_COUNT); diff --git a/src/freedreno/vulkan/tu_pipeline.cc b/src/freedreno/vulkan/tu_pipeline.cc index ba56cfd54c5..21c94faac02 100644 --- a/src/freedreno/vulkan/tu_pipeline.cc +++ b/src/freedreno/vulkan/tu_pipeline.cc @@ -1766,8 +1766,7 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, const VkPipelineCreationFeedbackCreateInfo *creation_feedback = vk_find_struct_const(builder->create_info->pNext, PIPELINE_CREATION_FEEDBACK_CREATE_INFO); - bool must_compile = - builder->state & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT; + bool must_compile = false; for (uint32_t i = 0; i < builder->create_info->stageCount; i++) { if (!(builder->active_stages & builder->create_info->pStages[i].stage)) continue; @@ -1854,9 +1853,7 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, for (gl_shader_stage stage = MESA_SHADER_VERTEX; stage < ARRAY_SIZE(nir); stage = (gl_shader_stage) (stage + 1)) { - if (stage_infos[stage] || nir[stage] || - (stage == MESA_SHADER_FRAGMENT && - (builder->state & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT))) { + if (stage_infos[stage] || nir[stage]) { bool shader_application_cache_hit; shader_sha1[20] = (unsigned char) stage; shaders[stage] = @@ -1920,16 +1917,6 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder, stage_feedbacks[stage].duration += os_time_get_nano() - stage_start; } - if (!nir[MESA_SHADER_FRAGMENT] && - (builder->state & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT)) { - const nir_shader_compiler_options *nir_options = - ir3_get_compiler_options(builder->device->compiler); - nir_builder fs_b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, - nir_options, - "noop_fs"); - nir[MESA_SHADER_FRAGMENT] = fs_b.shader; - } - if (executable_info) { for (gl_shader_stage stage = MESA_SHADER_VERTEX; stage < ARRAY_SIZE(nir); @@ -2020,14 +2007,25 @@ done: */ if (builder->state & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) { - for (gl_shader_stage stage = MESA_SHADER_TESS_CTRL; stage <= MESA_SHADER_GEOMETRY; - stage = (gl_shader_stage) (stage + 1)) { - if (!shaders[stage]) { - result = tu_empty_shader_create(builder->device, &shaders[stage], - stage); - if (result != VK_SUCCESS) - goto fail; - } + if (!shaders[MESA_SHADER_TESS_CTRL]) { + shaders[MESA_SHADER_TESS_CTRL] = builder->device->empty_tcs; + vk_pipeline_cache_object_ref(&shaders[MESA_SHADER_TESS_CTRL]->base); + } + if (!shaders[MESA_SHADER_TESS_EVAL]) { + shaders[MESA_SHADER_TESS_EVAL] = builder->device->empty_tes; + vk_pipeline_cache_object_ref(&shaders[MESA_SHADER_TESS_EVAL]->base); + } + if (!shaders[MESA_SHADER_GEOMETRY]) { + shaders[MESA_SHADER_GEOMETRY] = builder->device->empty_gs; + vk_pipeline_cache_object_ref(&shaders[MESA_SHADER_GEOMETRY]->base); + } + } + + if (builder->state & + VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) { + if (!shaders[MESA_SHADER_FRAGMENT]) { + shaders[MESA_SHADER_FRAGMENT] = builder->device->empty_fs; + vk_pipeline_cache_object_ref(&shaders[MESA_SHADER_FRAGMENT]->base); } } diff --git a/src/freedreno/vulkan/tu_shader.cc b/src/freedreno/vulkan/tu_shader.cc index 8013858877a..b3f9b3163ac 100644 --- a/src/freedreno/vulkan/tu_shader.cc +++ b/src/freedreno/vulkan/tu_shader.cc @@ -2289,7 +2289,7 @@ tu_shader_create(struct tu_device *dev, return VK_SUCCESS; } -VkResult +static VkResult tu_empty_shader_create(struct tu_device *dev, struct tu_shader **shader_out, gl_shader_stage stage) @@ -2322,6 +2322,74 @@ tu_empty_shader_create(struct tu_device *dev, return VK_SUCCESS; } +static VkResult +tu_empty_fs_create(struct tu_device *dev, struct tu_shader **shader) +{ + struct ir3_shader_key key = {}; + const struct ir3_shader_options options = {}; + struct ir3_stream_output_info so_info = {}; + const nir_shader_compiler_options *nir_options = + ir3_get_compiler_options(dev->compiler); + nir_builder fs_b; + + fs_b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, nir_options, + "noop_fs"); + + *shader = tu_shader_init(dev, NULL, 0); + if (!*shader) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + struct ir3_shader *ir3_shader = + ir3_shader_from_nir(dev->compiler, fs_b.shader, &options, &so_info); + (*shader)->variant = ir3_shader_create_variant(ir3_shader, &key, false); + + return tu_upload_shader(dev, *shader); +} + +VkResult +tu_init_empty_shaders(struct tu_device *dev) +{ + VkResult result; + + result = tu_empty_shader_create(dev, &dev->empty_tcs, MESA_SHADER_TESS_CTRL); + if (result != VK_SUCCESS) + goto out; + + result = tu_empty_shader_create(dev, &dev->empty_tes, MESA_SHADER_TESS_EVAL); + if (result != VK_SUCCESS) + goto out; + + result = tu_empty_shader_create(dev, &dev->empty_gs, MESA_SHADER_GEOMETRY); + if (result != VK_SUCCESS) + goto out; + + result = tu_empty_fs_create(dev, &dev->empty_fs); + if (result != VK_SUCCESS) + goto out; + + return VK_SUCCESS; + +out: + if (dev->empty_tcs) + vk_pipeline_cache_object_unref(&dev->vk, &dev->empty_tcs->base); + if (dev->empty_tes) + vk_pipeline_cache_object_unref(&dev->vk, &dev->empty_tes->base); + if (dev->empty_gs) + vk_pipeline_cache_object_unref(&dev->vk, &dev->empty_gs->base); + if (dev->empty_fs) + vk_pipeline_cache_object_unref(&dev->vk, &dev->empty_fs->base); + return result; +} + +void +tu_destroy_empty_shaders(struct tu_device *dev) +{ + vk_pipeline_cache_object_unref(&dev->vk, &dev->empty_tcs->base); + vk_pipeline_cache_object_unref(&dev->vk, &dev->empty_tes->base); + vk_pipeline_cache_object_unref(&dev->vk, &dev->empty_gs->base); + vk_pipeline_cache_object_unref(&dev->vk, &dev->empty_fs->base); +} + void tu_shader_destroy(struct tu_device *dev, struct tu_shader *shader) diff --git a/src/freedreno/vulkan/tu_shader.h b/src/freedreno/vulkan/tu_shader.h index 270e1dea05e..a89ebe07d9d 100644 --- a/src/freedreno/vulkan/tu_shader.h +++ b/src/freedreno/vulkan/tu_shader.h @@ -122,9 +122,10 @@ tu_shader_create(struct tu_device *dev, bool executable_info); VkResult -tu_empty_shader_create(struct tu_device *device, - struct tu_shader **shader_out, - gl_shader_stage stage); +tu_init_empty_shaders(struct tu_device *device); + +void +tu_destroy_empty_shaders(struct tu_device *device); void tu_shader_destroy(struct tu_device *dev,