diff --git a/src/asahi/vulkan/hk_cmd_draw.c b/src/asahi/vulkan/hk_cmd_draw.c index d4c408f9f30..2d71f49fd73 100644 --- a/src/asahi/vulkan/hk_cmd_draw.c +++ b/src/asahi/vulkan/hk_cmd_draw.c @@ -1636,8 +1636,18 @@ hk_cmd_bind_graphics_shader(struct hk_cmd_buffer *cmd, const gl_shader_stage stage, struct hk_api_shader *shader) { + struct hk_device *dev = hk_cmd_buffer_device(cmd); struct vk_dynamic_graphics_state *dyn = &cmd->vk.dynamic_graphics_state; + /* Null fragment shaders are annoying to handle, because we may still need an + * actual fragment shader to attach a prolog to. Rather than adding special + * cases, we just bind an empty fragment shader instead of NULL to make + * everything work correctly. + */ + if (stage == MESA_SHADER_FRAGMENT && shader == NULL) { + shader = dev->null_fs; + } + assert(stage < ARRAY_SIZE(cmd->state.gfx.shaders)); if (cmd->state.gfx.shaders[stage] == shader) return; diff --git a/src/asahi/vulkan/hk_device.c b/src/asahi/vulkan/hk_device.c index cf2cef41522..6d05e597f1d 100644 --- a/src/asahi/vulkan/hk_device.c +++ b/src/asahi/vulkan/hk_device.c @@ -20,6 +20,7 @@ #include "asahi/lib/agx_bo.h" #include "asahi/lib/agx_device.h" #include "asahi/libagx/geometry.h" +#include "compiler/nir/nir_builder.h" #include "util/hash_table.h" #include "util/ralloc.h" #include "util/simple_mtx.h" @@ -466,6 +467,23 @@ hk_CreateDevice(VkPhysicalDevice physicalDevice, if (result != VK_SUCCESS) goto fail_mem_cache; + /* Precompile an empty fragment shader that can be used to handle API-level + * null fragment shaders. We do this at device-time to make binds cheap. + * Regardless, compiling this shader should be fast. + */ + nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, + &agx_nir_options, "empty FS"); + struct vk_shader_compile_info info = { + .nir = b.shader, + .robustness = &vk_robustness_disabled, + .stage = MESA_SHADER_FRAGMENT, + }; + hk_compile_shader(dev, &info, NULL, pAllocator, &dev->null_fs); + if (!dev->null_fs) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto fail_meta; + } + *pDevice = hk_device_to_handle(dev); simple_mtx_init(&dev->scratch.lock, mtx_plain); @@ -479,6 +497,8 @@ hk_CreateDevice(VkPhysicalDevice physicalDevice, return VK_SUCCESS; +fail_meta: + hk_device_finish_meta(dev); fail_mem_cache: vk_pipeline_cache_destroy(dev->mem_cache, NULL); fail_queue: @@ -534,6 +554,10 @@ hk_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator) agx_scratch_fini(&dev->scratch.cs); simple_mtx_destroy(&dev->scratch.lock); + if (dev->null_fs) { + hk_api_shader_destroy(&dev->vk, &dev->null_fs->vk, pAllocator); + } + hk_destroy_sampler_heap(dev, &dev->samplers); hk_descriptor_table_finish(dev, &dev->images); hk_descriptor_table_finish(dev, &dev->occlusion_queries); diff --git a/src/asahi/vulkan/hk_device.h b/src/asahi/vulkan/hk_device.h index 6e980ade4da..651e865e2d0 100644 --- a/src/asahi/vulkan/hk_device.h +++ b/src/asahi/vulkan/hk_device.h @@ -98,7 +98,7 @@ struct hk_device { struct hk_internal_shaders prolog_epilog; struct hk_internal_shaders kernels; - struct hk_api_shader *write_shader; + struct hk_api_shader *null_fs; /* Indirected for common secondary emulation */ struct vk_device_dispatch_table cmd_dispatch;