diff options
| author | Lujin Wang <143145775+lujinwangnv@users.noreply.github.com> | 2025-09-26 16:07:13 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-26 23:07:13 +0000 |
| commit | 99de1a6203f676955f80de8c93c0f56c91d4ca96 (patch) | |
| tree | 2db039fb597a55cf455747eda31d35f578ceda0c /source/slang/slang-emit-spirv.cpp | |
| parent | e9f74ebfa83cd6aca39d7e3da2801cd47935bd1a (diff) | |
Add SPV_NV_bindless_texture support (#8534)
Treat DescriptorHandle as uint64_t instead of uint2. Implement
target-specific SPIR-V emission with the bindless texture support.
For OpImageTexelPointer, Image must have a type of OpTypePointer with
Type OpTypeImage. Fix the issue by using [constref] in __subscript.
Add a test coverage for various texture/sampler handle types.
---------
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'source/slang/slang-emit-spirv.cpp')
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 87 |
1 files changed, 85 insertions, 2 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 18c54587a..7b1bd66d8 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -1500,12 +1500,30 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex m_addressingMode, m_memoryModel); + // Emit OpSamplerImageAddressingModeNV if bindless texture capability is enabled + auto targetCaps = m_targetProgram->getTargetReq()->getTargetCaps(); + + if (targetCaps.implies(CapabilityAtom::spvBindlessTextureNV)) + { + requireSPIRVCapability((SpvCapability)SpvCapabilityBindlessTextureNV); + requireSPIRVCapability(SpvCapabilityInt64); // Required for 64-bit addressing mode + ensureExtensionDeclaration(UnownedStringSlice("SPV_NV_bindless_texture")); + + emitInstCustomOperandFunc( + getSection(SpvLogicalSectionID::MemoryModel), + nullptr, + SpvOpSamplerImageAddressingModeNV, + [&]() + { + emitOperand(SpvWord(64)); // 64-bit addressing mode + }); + } + if (m_memoryModel == SpvMemoryModelVulkan) { requireSPIRVCapability(SpvCapabilityVulkanMemoryModel); ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_vulkan_memory_model")); - auto targetCaps = m_targetProgram->getTargetReq()->getTargetCaps(); if (targetCaps.implies(CapabilityAtom::spvVulkanMemoryModelDeviceScopeKHR)) { requireSPIRVCapability(SpvCapabilityVulkanMemoryModelDeviceScope); @@ -2129,7 +2147,25 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex { IRBuilder builder(inst); builder.setInsertBefore(inst); - return emitOpTypeVector(inst, builder.getUIntType(), SpvLiteralInteger::from32(2)); + auto targetCaps = m_targetProgram->getTargetReq()->getTargetCaps(); + + if (targetCaps.implies(CapabilityAtom::spvBindlessTextureNV)) + { + // For spvBindlessTextureNV, DescriptorHandleType should be a uint64_t + // (OpTypeInt 64 0) + return emitOpTypeInt( + inst, + SpvLiteralInteger::from32(64), + SpvLiteralInteger::from32(0)); + } + else + { + // For other targets, use uint2 (OpTypeVector of 2 uint32) + return emitOpTypeVector( + inst, + builder.getUIntType(), + SpvLiteralInteger::from32(2)); + } } case kIROp_SubpassInputType: return ensureSubpassInputType(inst, cast<IRSubpassInputType>(inst)); @@ -4154,12 +4190,59 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex case kIROp_CastDescriptorHandleToUInt2: case kIROp_CastUInt2ToDescriptorHandle: case kIROp_GlobalValueRef: + case kIROp_CastUInt64ToDescriptorHandle: + case kIROp_CastDescriptorHandleToUInt64: { auto inner = ensureInst(inst->getOperand(0)); registerInst(inst, inner); result = inner; break; } + case kIROp_CastDescriptorHandleToResource: + // Convert DescriptorHandle (uint64_t handle) to appropriate resource type + { + auto targetCaps = m_targetProgram->getTargetReq()->getTargetCaps(); + + if (targetCaps.implies(CapabilityAtom::spvBindlessTextureNV)) + { + requireSPIRVCapability((SpvCapability)SpvCapabilityBindlessTextureNV); + ensureExtensionDeclaration(UnownedStringSlice("SPV_NV_bindless_texture")); + + auto operand = ensureInst(inst->getOperand(0)); + SpvOp conversionOp = SpvOpConvertUToSampledImageNV; + IRType* resultType = inst->getDataType(); + + switch (resultType->getOp()) + { + case kIROp_TextureType: + conversionOp = SpvOpConvertUToSampledImageNV; + result = emitInst( + parent, + inst, + conversionOp, + inst->getDataType(), + kResultID, + operand); + break; + case kIROp_SamplerStateType: + conversionOp = SpvOpConvertUToSamplerNV; + result = emitInst( + parent, + inst, + conversionOp, + inst->getDataType(), + kResultID, + operand); + break; + default: + // Unsupported result type for descriptor-to-resource conversion + SLANG_UNEXPECTED( + "Unsupported result type for CastDescriptorHandleToResource"); + break; + } + } + break; + } case kIROp_GetVulkanRayTracingPayloadLocation: { IRInst* location = getVulkanPayloadLocation(inst->getOperand(0)); |
