ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Slang 纹理足迹查询(Texture Footprint Queries)实战指南:精准预测纹理采样访问范围

Slang 纹理足迹查询(Texture Footprint Queries)实战指南:精准预测纹理采样访问范围 编译器图形学编程语言【免费下载链接】slangMaking it easier to work with shaders项目地址https://gitcode.com/GitHub_Trending/sl/slang点击查看免费下载本文围绕 docs/gpu-feature/texture/footprint-queries.md 展开结合 Slang 源码source/slang/hlsl.meta.slang、source/slang/slang-capabilities.capdef与测试用例tests/gpu-feature/texture/query/footprint进行纵深讲解。Slang 为着色器开发提供了一套统一的纹理足迹查询Texture Footprint QueryAPI让应用能够以与真实采样完全一致的采样器状态和纹理坐标预先查询一次纹理采样操作会访问到的纹素范围footprint。本文讲解该特性的背景动机、Texture2D/Texture3D上的全部查询函数签名与参数语义、TextureFootprint2D/TextureFootprint3D返回结构的字段解码规则并结合源码揭示其在 VulkanGLSL/SPIR-V与 D3D12NVAPI两条后端路径上的映射实现与能力约束帮助你在阴影贴图裁剪、可见性优化等场景中直接落地使用。背景为什么需要查询纹理足迹在大量 GPU 渲染管线中存在一类典型模式先生成一张纹理例如渲染到纹理随后在三维渲染 pass 中采样它。难点在于光照、遮挡等因素导致无法在生成阶段预先确定纹理的哪些区域最终会被访问到。以阴影贴图为例渲染 g-buffer 时逐像素阴影采样会读取阴影贴图的某个区域。由于 g-buffer 中几何体的形状与遮挡关系未知阴影贴图的某些部分可能完全用不到。理论上应用可以对 g-buffer 做一次 compute pass为每个像素计算出它将要访问的阴影贴图区域即 footprint再把这些 footprint 聚合为 stencil mask 或其它数据结构用来优化生成阴影贴图的渲染 pass——只渲染真正会被用到的部分。然而一旦涉及非平凡的纹理过滤模式应用几乎不可能准确、可靠地自行预测某次采样操作到底需要哪些纹素启用双线性过滤时采样通常访问采样点周围最近的 4 个纹素并混合启用三线性过滤时采样可能同时访问两个 mip 层级启用各向异性过滤时采样可能最多取 N 个tapN 为最大支持的各向异性度数每个 tap 自身还可能访问一片纹素邻域来完成过滤采样立方体贴图时采样操作可能跨越两个甚至三个 cube 面之间的接缝。纹理足迹查询正是为解决此问题而生它为开发者提供一个原语使用与稍后真实采样完全相同的采样器状态与纹理坐标查询该采样操作的足迹。Slang 在 Vulkan 上通过GL_NV_shader_texture_footprint扩展支持该特性在 D3D12 上则通过 NVAPI 暴露的NvFootprint*系列函数支持。Slang Shader API 基础用法与逐一镜像 Vulkan GLSL 扩展或 NVAPI 函数不同Slang 核心模块core module提供了一套统一的公共接口可分别映射到上述两种实现。这样写出的着色器代码天然可移植。一个典型的 2D 纹理采样操作使用Texture2D的Sample()方法Texture2Dfloat4 texture ...; SamplerState sampler ...; float2 coords ...; // 采样一张 2D 纹理 float4 color texture.Sample( sampler, coords);要查询这次操作会访问的足迹只需把同样的参数原样传给queryFootprintCoarseuint granularity ...; TextureFootprint2D footprint texture.queryFootprintCoarse(granularity, sampler, coords);注意上面传给Sample的参数在queryFootprint中以完全相同的顺序再次传入返回的footprint编码了等效Sample操作所访问纹素的保守conservative足迹——即覆盖了真实采样可能访问到的所有纹素只多不少。纹理足迹以纹素块blocks of texels为单位编码块的大小由granularity决定。granularity参数表示应用请求的块粒度。当一次过滤操作可能访问两个 mip 层级一个较粗、一个较细时足迹查询只返回其中一个层级的信息。应用通过选择调用queryFootprintCoarse或queryFootprintFine来决定取粗层还是细层。查询函数全览2D 纹理针对带不同参数的各类采样场景Slang 提供了一组覆盖面很广的足迹查询函数。2D 纹理支持的完整函数集如下TextureFootprint2D Texture2D.queryFootprintCoarse( uint granularity, SamplerState sampler, float2 coords); TextureFootprint2D Texture2D.queryFootprintFine( uint granularity, SamplerState sampler, float2 coords); TextureFootprint2D Texture2D.queryFootprintCoarseBias( uint granularity, SamplerState sampler, float2 coords, float lodBias); TextureFootprint2D Texture2D.queryFootprintFineBias( uint granularity, SamplerState sampler, float2 coords, float lodBias); TextureFootprint2D Texture2D.queryFootprintCoarseLevel( uint granularity, SamplerState sampler, float2 coords, float lod); TextureFootprint2D Texture2D.queryFootprintFineLevel( uint granularity, SamplerState sampler, float2 coords, float lod); TextureFootprint2D Texture2D.queryFootprintCoarseGrad( uint granularity, SamplerState sampler, float2 coords, float2 dx, float2 dy); TextureFootprint2D Texture2D.queryFootprintFineGrad( uint granularity, SamplerState sampler, float2 coords, float2 dx, float2 dy); // Vulkan-only: TextureFootprint2D Texture2D.queryFootprintCoarseClamp( uint granularity, SamplerState sampler, float2 coords, float lodClamp); TextureFootprint2D Texture2D.queryFootprintFineClamp( uint granularity, SamplerState sampler, float2 coords, float lodClamp); TextureFootprint2D Texture2D.queryFootprintCoarseBiasClamp( uint granularity, SamplerState sampler, float2 coords, float lodBias, float lodClamp); TextureFootprint2D Texture2D.queryFootprintFineBiasClamp( uint granularity, SamplerState sampler, float2 coords, float lodBias, float lodClamp); TextureFootprint2D Texture2D.queryFootprintCoarseGradClamp( uint granularity, SamplerState sampler, float2 coords, float2 dx, float2 dy, float lodClamp); TextureFootprint2D Texture2D.queryFootprintFineGradClamp( uint granularity, SamplerState sampler, float2 coords, float2 dx, float2 dy, float lodClamp);各变体的语义对照后缀含义额外参数Coarse/Fine在双 mip 采样时选择粗层 / 细层足迹无Bias与SampleBias对应携带 LOD 偏移float lodBiasLevel与SampleLevel对应直接指定 mip 层级float lodGrad与SampleGrad对应显式提供屏幕空间导数float2 dx, float2 dyClampVulkan-only额外夹紧最小 LODfloat lodClampBias、Level、Grad、Clamp可互相组合分别对应 HLSL 采样 API 中SampleBias、SampleLevel、SampleGrad以及稀疏纹理夹紧的语义保证查询与真实采样在 LOD 选择逻辑上完全一致。Grad变体只对 2D 纹理提供——从源码注释source/slang/hlsl.meta.slang 中 Texture sampling with gradient is only available for 2D textures可以确认梯度采样在 GLSL/NVAPI 扩展层面都仅支持 2D。查询函数全览3D 纹理3D 纹理支持的函数集如下注意没有Grad变体TextureFootprint3D Texture3D.queryFootprintCoarse( uint granularity, SamplerState sampler, float3 coords); TextureFootprint3D Texture3D.queryFootprintFine( uint granularity, SamplerState sampler, float3 coords); TextureFootprint3D Texture3D.queryFootprintCoarseBias( uint granularity, SamplerState sampler, float3 coords, float lodBias); TextureFootprint3D Texture3D.queryFootprintFineBias( uint granularity, SamplerState sampler, float3 coords, float lodBias); TextureFootprint3D Texture3D.queryFootprintCoarseLevel( uint granularity, SamplerState sampler, float3 coords, float lod); TextureFootprint3D Texture3D.queryFootprintFineLevel( uint granularity, SamplerState sampler, float3 coords, float lod); // Vulkan-only: TextureFootprint3D Texture3D.queryFootprintCoarseClamp( uint granularity, SamplerState sampler, float3 coords, float lodClamp); TextureFootprint3D Texture3D.queryFootprintFineClamp( uint granularity, SamplerState sampler, float3 coords, float lodClamp); TextureFootprint3D Texture3D.queryFootprintCoarseBiasClamp( uint granularity, SamplerState sampler, float3 coords, float lodBias, float lodClamp); TextureFootprint3D Texture3D.queryFootprintFineBiasClamp( uint granularity, SamplerState sampler, float3 coords, float lodBias, float lodClamp);与 2D 相比3D 版本的区别在于坐标类型为float3、返回类型为TextureFootprint3D且缺少Grad/GradClamp系列。其余Bias、Level、Clamp组合与 2D 一一对应。足迹类型TextureFootprint2D / TextureFootprint3D2D 与 3D 的足迹查询分别返回内置结构体TextureFootprint2D与TextureFootprint3D二者定义于 Slang 核心模块struct TextureFootprint2D { typealias Anchor uint2; typealias Offset uint2; typealias Mask uint2; typealias LOD uint; typealias Granularity uint; property anchor : Anchor { get; } property offset : Offset { get; } property mask : Mask { get; } property lod : LOD { get; } property granularity : Granularity { get; } property isSingleLevel : bool { get; } } struct TextureFootprint3D { typealias Anchor uint3; typealias Offset uint3; typealias Mask uint2; typealias LOD uint; typealias Granularity uint; property anchor : Anchor { get; } property offset : Offset { get; } property mask : Mask { get; } property lod : LOD { get; } property granularity : Granularity { get; } property isSingleLevel : bool { get; } }足迹以texel group纹素组为单位编码granularity决定组的大小。在可能的情况下返回的足迹会匹配查询时传入的 granularity但当地址过于庞大、无法以请求的粒度编码时实现可能选择更大的粒度——因此读取结果时始终应以返回的granularity字段为准。各字段的语义如下字段类型含义anchoruint2/uint3纹理中位于足迹附近的一个锚点各分量的单位是8 个 texel group的倍数offsetuint2/uint3说明mask中的各 bit 如何映射到anchor附近的 texel groupmaskuint264 位位域每一位表示一个 texel group 的足迹覆盖情况作用于锚点附近 8x82D或 4x4x43D的 texel group 邻域loduint采样操作将要访问的 mipmap 层级granularityuint本次返回的足迹实际采用的粒度isSingleLevelbool采样操作是否已知只访问单一 mip 层级。注意走 D3D/NVAPI 路径时该字段恒为false解码提示mask是一个 64 位位域编码在uint2中配合anchor与offset即可还原出被覆盖 texel group 的精确空间位置。2D 情况下anchoroffset 8x8 掩码可覆盖一个局部窗口应用在聚合多个像素的 footprint 时通常以anchor对齐到固定块边界、再用mask做按位合并。源码级实现统一接口如何映射到两条后端统一 API 的背后是_Texture扩展与内部 intrinsic 的映射机制全部位于 source/slang/hlsl.meta.slang约第 26900–27540 行。类型定义TextureFootprintND是模板化的内部类型TextureFootprint2D/TextureFootprint3D只是其特化别名typealias TextureFootprint2D TextureFootprint2底层数据由__TextureFootprintDataND承载其anchor/offset等属性通过__textureFootprintGetAnchor(this, ND)等 intrinsic 按维度访问mask统一为uint2所有查询函数通过extension _TextureT, Shape, ...以扩展方法的形式挂载到纹理类型上并额外暴露Footprint、Coarse、FootprintGranularity等类型别名方便书写Texture2D.Footprint这类成员访问。GLSL / SPIR-VVulkan路径GLSL 路径的 intrinsic 通过__target_switch分别实现GLSL 目标直接发射textureFootprintNV/textureFootprintClampNV/textureFootprintLodNV/textureFootprintGradNV/textureFootprintGradClampNVintrinsicSPIR-V 目标内联spirv_asm发射OpImageSampleFootprintNV指令同时声明ImageFootprintNVcapability 与SPV_NV_shader_image_footprint扩展带Clamp的变体额外追加MinLodcapability 与MinLod操作数带Bias/Lod/Grad的变体则分别追加对应的图像操作数Coarse/Fine 的选择在 GLSL/SPIR-V 一侧被编码为一个bool参数useCoarseLevel传给 intrinsic从源码注释可以确认尽管 GLSL 扩展把结果的granularity成员定义为uint但各查询函数签名中的 granularity 参数实际是int类型。NVAPID3D12路径NVAPI 路径则把 Coarse/Fine 选择编码进函数名NvFootprintCoarse、NvFootprintFine等因此源码中利用宏模板kLevelChoices数组循环展开为Coarse/Fine各生成一套__queryFootprint...NVAPIintrinsic依次对应NvFootprint$(CoarseOrFine)、NvFootprint$(CoarseOrFine)Bias、NvFootprint$(CoarseOrFine)Level、NvFootprint$(CoarseOrFine)Grad。这些 intrinsic 以NV_EXTN_TEXTURE_${ND}D宏引用纹理类型并输出isSingleLod标志。这也解释了为什么isSingleLevel在 D3D 路径下恒为false——NVAPI 的NvFootprint*系列并不携带这一信息。统一入口的分发逻辑每个公共查询方法如queryFootprintCoarse内部是一个薄封装对 Vulkan 目标调用__queryFootprintGLSL(...)把返回的bool结果写入footprint._isSingleLevel对 D3D12 目标调用__queryFootprint...NVAPI(...)。从而做到一份着色器代码、双后端零改写。同时源码注释指出NVAPI 函数本支持可选的 texel offset 参数但由于 GLSL 扩展中没有对应物目前未提供带该参数的重载——这是跨后端统一 API 时主动做的取舍。能力声明与编译期约束texturefootprint与texturefootprintclamp是 Slang 特性系统中的正式能力capability定义于 source/slang/slang-capabilities.capdefalias texturefootprint GL_NV_shader_texture_footprint GLSL_450 | hlsl_nvapi _sm_4_0; alias texturefootprintclamp texturefootprint GL_ARB_sparse_texture_clamp;由此可以提炼出两条关键约束基础足迹查询要求满足以下任一条件Vulkan 上为GL_NV_shader_texture_footprint扩展 GLSL 450D3D12 上为 NVAPIhlsl_nvapi Shader Model 4.0 及以上Clamp变体Vulkan-only在基础能力之上额外要求GL_ARB_sparse_texture_clamp扩展——这正是文档中把Clamp系列标注为 Vulkan-only 的根本原因NVAPI 路径没有对应实现。同时hlsl.meta.slang 中所有 footprint intrinsic 均标注[__NoSideEffect]无副作用部分还带有[__requiresNVAPI]标记说明这类查询在着色器中是纯查询操作可被 DCE死代码消除等优化安全处理。对应地在 source/slang/slang-capabilities.capdef 中该能力还被纳入 NVIDIA 专属扩展集合与shaderclock、fragmentshaderinterlock等能力并列。测试用例如何验证足迹查询仓库在 tests/gpu-feature/texture/query/footprint 下提供了三组针对该特性的测试直接印证了上文所述的映射关系nv-shader-texture-footprint-simple.slang最简用例验证 SPIR-V 输出包含OpExtension SPV_NV_shader_image_footprint与OpImageSampleFootprintNVHLSL 输出包含NvFootprintCoarse并通过一个accumulate异或累加器把查询结果的每个字段anchor、offset、mask、lod、granularity、isSingleLevel都引用一遍防止优化器把未被使用的查询 DCE 掉nv-shader-texture-footprint.slang覆盖 Clamp 变体并对 HLSL 输出逐字段断言NvFootprintExtractAnchorTileLoc2D、NvFootprintExtractOffset2D、NvFootprintExtractBitmask、NvFootprintExtractLOD、NvFootprintExtractReturnGran等 NVAPI 字段提取 intrinsicnv-shader-texture-footprint-array.slang针对纹理数组变体的补充覆盖。这些测试文件头部以//TEST:SIMPLE标注了针对spirv-assembly、spirv、hlsl等目标的编译验证方式同时保留了针对 DXIL 与-emit-spirv-directly路径的DISABLED_TEST记录文件注释说明 SPIR-V 测试本地通过但曾在 CI 中导致难以调试的挂起故暂被禁用——如果你要为本特性补充测试可以参考这套 filecheck 断言风格。使用建议与限制小结采样参数一致性足迹查询必须使用与后续真实采样完全相同的 sampler、坐标与 LOD 参数否则查询结果失去意义Bias/Level/Grad/Clamp变体正是为此而设粒度权衡granularity越小footprint 编码越精细但可能触发实现回退到更大粒度应用应以返回值的granularity字段为准进行聚合保守性查询返回的是保守足迹覆盖真实访问范围可用于构建 stencil mask、可见性剔除等宁多勿少的场景双 mip 选择三线性等双层级采样时请根据用途决定调用Coarse还是Fine版本平台差异Clamp变体仅限 VulkanisSingleLevel在 D3D/NVAPI 路径恒为falseGrad变体仅 2D 纹理可用硬件前提该特性依赖 NVIDIA 扩展Vulkan 的GL_NV_shader_texture_footprint/SPV_NV_shader_image_footprint或 D3D12 的 NVAPI部署前应通过 capability 机制如[require(glsl_spirv, texturefootprint)]在着色器内声明依赖确保只在支持的目标上启用相关代码路径。掌握了上述 API 与底层映射你就可以在 Slang 中写出跨 Vulkan/D3D12 的足迹查询着色器为阴影贴图裁剪、纹理流送等 GPU 优化场景提供准确的采样范围预测。赞分享编译器图形学编程语言【免费下载链接】slangMaking it easier to work with shaders项目地址https://gitcode.com/GitHub_Trending/sl/slang点击查看免费下载相关推荐three.js TSL 节点详解Texture3DNode 与三维纹理采样3D Texture / Data3DTexturethree.js TSL 节点详解Texture3DNode 与三维纹理采样3D Texture / Data3DTexture 导读 Texture3D前端3D渲染图形学cuda-samples 之 simpleLayeredTextureCUDA 分层 2D 纹理Layered Texture的创建、采样与验证指南cuda samples 之 simpleLayeredTextureCUDA 分层 2D 纹理Layered Texture的创建、采样与验证指南 导读示例工程PWA上线前必查清单serviceworker-rails生产部署中Sprockets预编译与CDN的4个坑PWA上线前必查清单serviceworker rails生产部署中Sprockets预编译与CDN的4个坑 serviceworker rails 是 Ra创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表