nvk: Reserve a sampler for TXF on Kepler

The SPIR-V spec says texelFetch and friends don't take a sampler.
However, on Kepler and earlier hardware, the sampler is read even for
tld.  In particular, the hardware reads the sRGB conversion bit in the
sampler and this can be in an inconsistent state if we haven't
initialized samplers properly.  On Kepler, we should just reserve a
sampler at device creation time and always use that for tld.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35190>
This commit is contained in:
Faith Ekstrand
2025-05-27 17:02:54 -04:00
committed by Marge Bot
parent bfdc95b109
commit 8ffe0098be
4 changed files with 61 additions and 6 deletions
+18
View File
@@ -8,6 +8,7 @@
#include "nvk_entrypoints.h"
#include "nvk_instance.h"
#include "nvk_physical_device.h"
#include "nvk_sampler.h"
#include "nvk_shader.h"
#include "nvkmd/nvkmd.h"
@@ -200,6 +201,23 @@ nvk_CreateDevice(VkPhysicalDevice physicalDevice,
if (result != VK_SUCCESS)
goto fail_images;
/* On Kepler and earlier, TXF takes a sampler but SPIR-V defines it as not
* taking one so we need to reserve one at device create time. If we do so
* now then it will always have sampler index 0 so we can rely on that in
* the compiler lowering code (similar to null descriptors).
*/
if (pdev->info.cls_eng3d < MAXWELL_A) {
uint32_t txf_sampler[8] = {};
nvk_fill_txf_sampler_header(pdev, txf_sampler);
ASSERTED uint32_t txf_sampler_index;
result = nvk_descriptor_table_add(dev, &dev->samplers,
txf_sampler, sizeof(txf_sampler),
&txf_sampler_index);
assert(result == VK_SUCCESS);
assert(txf_sampler_index == 0);
}
if (dev->vk.enabled_features.descriptorBuffer ||
nvk_use_edb_buffer_views(pdev)) {
result = nvk_edb_bview_cache_init(dev, &dev->edb_bview_cache);
+16 -1
View File
@@ -12,6 +12,7 @@
#include "nir_builder.h"
#include "nir_deref.h"
#include "clb097.h"
#include "clc397.h"
#include "clc597.h"
@@ -1301,7 +1302,21 @@ lower_tex(nir_builder *b, nir_tex_instr *tex,
load_resource_deref_desc(b, 1, 32, texture, plane_offset_B, ctx);
nir_def *combined_handle;
if (texture == sampler || !nir_tex_instr_need_sampler(tex)) {
if (!nir_tex_instr_need_sampler(tex)) {
combined_handle = texture_desc;
/* On Kepler and earlier, TXF takes a sampler but SPIR-V defines it as
* not taking one so we can't trust the sampler from the client's image
* descriptor. Instead, mask off the top bits so we get a zero sampler
* index which we've conveniently reserved at device cration time for a
* special TXF sampler.
*/
if (ctx->dev_info->cls_eng3d < MAXWELL_A) {
combined_handle = nir_iand_imm(b, combined_handle,
NVK_IMAGE_DESCRIPTOR_IMAGE_INDEX_MASK);
}
} else if (texture == sampler) {
combined_handle = texture_desc;
} else {
combined_handle = nir_iand_imm(b, texture_desc,
+24
View File
@@ -282,6 +282,30 @@ nvk_sampler_fill_header(const struct nvk_physical_device *pdev,
SAMP_SET_U(samp, NV9097, 7, BORDER_COLOR_A, bc.uint32[3]);
}
void
nvk_fill_txf_sampler_header(const struct nvk_physical_device *pdev,
uint32_t *samp)
{
const VkSamplerCreateInfo sampler_info = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.magFilter = VK_FILTER_NEAREST,
.minFilter = VK_FILTER_NEAREST,
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
.borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,
.minLod = 0.0,
.maxLod = 16.0,
.unnormalizedCoordinates = true,
};
struct vk_sampler sampler;
vk_sampler_init(&sampler_info, &sampler);
nvk_sampler_fill_header(pdev, &sampler_info, &sampler, samp);
}
VKAPI_ATTR VkResult VKAPI_CALL
nvk_CreateSampler(VkDevice device,
const VkSamplerCreateInfo *pCreateInfo,
+3 -5
View File
@@ -32,10 +32,8 @@ struct nvk_sampler_capture {
} planes[NVK_MAX_SAMPLER_PLANES];
};
static void
nvk_sampler_fill_header(const struct nvk_physical_device *pdev,
const struct VkSamplerCreateInfo *info,
const struct vk_sampler *vk_sampler,
uint32_t *samp);
void
nvk_fill_txf_sampler_header(const struct nvk_physical_device *pdev,
uint32_t *samp);
#endif