diff --git a/src/nouveau/vulkan/nvk_device.c b/src/nouveau/vulkan/nvk_device.c index fb338ed2d4d..024677edc6d 100644 --- a/src/nouveau/vulkan/nvk_device.c +++ b/src/nouveau/vulkan/nvk_device.c @@ -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); diff --git a/src/nouveau/vulkan/nvk_nir_lower_descriptors.c b/src/nouveau/vulkan/nvk_nir_lower_descriptors.c index ff24dab65a9..9193a39f953 100644 --- a/src/nouveau/vulkan/nvk_nir_lower_descriptors.c +++ b/src/nouveau/vulkan/nvk_nir_lower_descriptors.c @@ -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, diff --git a/src/nouveau/vulkan/nvk_sampler.c b/src/nouveau/vulkan/nvk_sampler.c index bc2e8c9ce14..3ee6b252f13 100644 --- a/src/nouveau/vulkan/nvk_sampler.c +++ b/src/nouveau/vulkan/nvk_sampler.c @@ -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, diff --git a/src/nouveau/vulkan/nvk_sampler.h b/src/nouveau/vulkan/nvk_sampler.h index 06b44cf3a7e..e1337c82716 100644 --- a/src/nouveau/vulkan/nvk_sampler.h +++ b/src/nouveau/vulkan/nvk_sampler.h @@ -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