hk: fix null FS corner cases

this fixes null FS + cull distance/API sample mask, which require a prolog.
fixes upcoming CTS.

Backport-to: 25.1
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34585>
(cherry picked from commit 3ab8ce8579c967e1d8fb024de298a958511d9ffd)
This commit is contained in:
Alyssa Rosenzweig
2025-04-17 11:56:18 -04:00
committed by Eric Engestrom
parent 5c048f7860
commit 3cc215b1cc
4 changed files with 36 additions and 2 deletions

View File

@@ -1424,7 +1424,7 @@
"description": "hk: fix null FS corner cases",
"nominated": true,
"nomination_type": 4,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;