diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2023-09-20 00:56:12 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-19 09:56:12 -0700 |
| commit | 359fdc9d556b4c493c588c5b8f93df85933634f8 (patch) | |
| tree | a4f96b061267277f3bfe90c55981e2dffa3f99b3 /source | |
| parent | da3069668639c51f38e7616e4177ce04a8b2c57c (diff) | |
Handle combined image and samplers in spirv (#3213)
* Handle combined image and samplers in spirv
* less expected failure
---------
Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-emit-spirv-ops.h | 9 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 279 |
2 files changed, 152 insertions, 136 deletions
diff --git a/source/slang/slang-emit-spirv-ops.h b/source/slang/slang-emit-spirv-ops.h index 42a2023fc..9c4ec290d 100644 --- a/source/slang/slang-emit-spirv-ops.h +++ b/source/slang/slang-emit-spirv-ops.h @@ -229,6 +229,15 @@ SpvInst* emitOpTypeSampler(IRInst* inst) ); } +// https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeSampler +template<typename T1> +SpvInst* emitOpTypeSampledImage(IRInst* inst, const T1& imageType) +{ + return emitInstMemoized( + getSection(SpvLogicalSectionID::ConstantsAndTypes), inst, SpvOpTypeSampledImage, kResultID, imageType + ); +} + SpvInst* emitOpTypeAccelerationStructure(IRInst* inst) { return emitInstMemoized( diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 690c6d77b..2be86cdfe 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -1314,144 +1314,14 @@ struct SPIRVEmitContext return arrayType; } case kIROp_TextureType: - { - // Some untyped constants from OpTypeImage - // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage - - // indicates not a depth image - [[maybe_unused]] - const SpvWord notDepthImage = 0; - // indicates a depth image - [[maybe_unused]] - const SpvWord isDepthImage = 1; - // means no indication as to whether this is a depth or non-depth image - const SpvWord unknownDepthImage = 2; - - // indicates non-arrayed content - const SpvWord notArrayed = 0; - // indicates arrayed content - const SpvWord isArrayed = 1; - - // indicates single-sampled content - const SpvWord notMultisampled = 0; - // indicates multisampled content - const SpvWord isMultisampled = 1; - - // indicates this is only known at run time, not at compile time - const SpvWord sampledUnknown = 0; - // indicates an image compatible with sampling operations - const SpvWord sampledImage = 1; - // indicates an image compatible with read/write operations (a storage or subpass data image). - const SpvWord readWriteImage = 2; - - // - - const auto texTypeInst = as<IRTextureType>(inst); - const auto sampledType = texTypeInst->getElementType(); - SpvDim dim = SpvDim1D; // Silence uninitialized warnings from msvc... - switch(texTypeInst->GetBaseShape()) - { - case TextureFlavor::Shape1D: - case TextureFlavor::Shape1DArray: - dim = SpvDim1D; - break; - case TextureFlavor::Shape2D: - case TextureFlavor::Shape2DArray: - dim = SpvDim2D; - break; - case TextureFlavor::Shape3D: - dim = SpvDim3D; - break; - case TextureFlavor::ShapeCube: - case TextureFlavor::ShapeCubeArray: - dim = SpvDimCube; - break; - case TextureFlavor::ShapeBuffer: - dim = SpvDimBuffer; - break; - } - SpvWord arrayed = texTypeInst->isArray() ? isArrayed : notArrayed; - - // Vulkan spec 16.1: "The “Depth” operand of OpTypeImage is ignored." - SpvWord depth = unknownDepthImage; // No knowledge of if this is a depth image - SpvWord ms = texTypeInst->isMultisample() ? isMultisampled : notMultisampled; - - SpvWord sampled = sampledUnknown; - switch(texTypeInst->getAccess()) - { - case SlangResourceAccess::SLANG_RESOURCE_ACCESS_READ_WRITE: - case SlangResourceAccess::SLANG_RESOURCE_ACCESS_RASTER_ORDERED: - sampled = readWriteImage; - break; - case SlangResourceAccess::SLANG_RESOURCE_ACCESS_NONE: - case SlangResourceAccess::SLANG_RESOURCE_ACCESS_READ: - sampled = sampledImage; - break; - } - - // TODO: we need to do as _emitGLSLImageFormatModifier does, - // take a guess at the image format - SpvImageFormat format = SpvImageFormatUnknown; - - // - // Capabilities, according to section 3.8 - // - // SPIR-V requires that the sampled/rw info on the image isn't unknown - SLANG_ASSERT(sampled == sampledImage || sampled == readWriteImage); - switch(dim) - { - case SpvDim1D: - requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampled1D : SpvCapabilityImage1D); - break; - case SpvDim2D: - // Also requires Shader or Kernel, but these are a given (?) - if(sampled == readWriteImage && ms == isMultisampled && arrayed == isArrayed) - requireSPIRVCapability(SpvCapabilityImageMSArray); - break; - case SpvDim3D: - break; - case SpvDimCube: - // Requires shader also - if(sampled == readWriteImage && arrayed == isArrayed) - requireSPIRVCapability(SpvCapabilityImageCubeArray); - break; - case SpvDimRect: - requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampledRect : SpvCapabilityImageRect); - break; - case SpvDimBuffer: - requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampledBuffer : SpvCapabilityImageBuffer); - break; - case SpvDimSubpassData: - requireSPIRVCapability(SpvCapabilityInputAttachment); - break; - case SpvDimTileImageDataEXT: - SLANG_UNIMPLEMENTED_X("OpTypeImage Capabilities for SpvDimTileImageDataEXT"); - break; - } - if(format == SpvImageFormatUnknown && sampled == readWriteImage) - { - // TODO: It may not be necessary to have both of these - // depending on if we read or write - requireSPIRVCapability(SpvCapabilityStorageImageReadWithoutFormat); - requireSPIRVCapability(SpvCapabilityStorageImageWriteWithoutFormat); - } - - // - // The op itself - // - return emitOpTypeImage( - inst, - dropVector(sampledType), - dim, - SpvLiteralInteger::from32(depth), - SpvLiteralInteger::from32(arrayed), - SpvLiteralInteger::from32(ms), - SpvLiteralInteger::from32(sampled), - format - ); - } + return ensureTextureType(inst, cast<IRTextureType>(inst)); case kIROp_SamplerStateType: return emitOpTypeSampler(inst); + case kIROp_TextureSamplerType: + return emitOpTypeSampledImage( + inst, + ensureTextureType(nullptr, cast<IRTextureTypeBase>(inst)) + ); case kIROp_RaytracingAccelerationStructureType: requireSPIRVCapability(SpvCapabilityRayTracingKHR); @@ -1584,6 +1454,143 @@ struct SPIRVEmitContext } } + SpvInst* ensureTextureType(IRInst* assignee, IRTextureTypeBase* inst) + { + // Some untyped constants from OpTypeImage + // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage + + // indicates not a depth image + [[maybe_unused]] + const SpvWord notDepthImage = 0; + // indicates a depth image + [[maybe_unused]] + const SpvWord isDepthImage = 1; + // means no indication as to whether this is a depth or non-depth image + const SpvWord unknownDepthImage = 2; + + // indicates non-arrayed content + const SpvWord notArrayed = 0; + // indicates arrayed content + const SpvWord isArrayed = 1; + + // indicates single-sampled content + const SpvWord notMultisampled = 0; + // indicates multisampled content + const SpvWord isMultisampled = 1; + + // indicates this is only known at run time, not at compile time + const SpvWord sampledUnknown = 0; + // indicates an image compatible with sampling operations + const SpvWord sampledImage = 1; + // indicates an image compatible with read/write operations (a storage or subpass data image). + const SpvWord readWriteImage = 2; + + // + + const auto sampledType = inst->getElementType(); + SpvDim dim = SpvDim1D; // Silence uninitialized warnings from msvc... + switch(inst->GetBaseShape()) + { + case TextureFlavor::Shape1D: + case TextureFlavor::Shape1DArray: + dim = SpvDim1D; + break; + case TextureFlavor::Shape2D: + case TextureFlavor::Shape2DArray: + dim = SpvDim2D; + break; + case TextureFlavor::Shape3D: + dim = SpvDim3D; + break; + case TextureFlavor::ShapeCube: + case TextureFlavor::ShapeCubeArray: + dim = SpvDimCube; + break; + case TextureFlavor::ShapeBuffer: + dim = SpvDimBuffer; + break; + } + SpvWord arrayed = inst->isArray() ? isArrayed : notArrayed; + + // Vulkan spec 16.1: "The “Depth” operand of OpTypeImage is ignored." + SpvWord depth = unknownDepthImage; // No knowledge of if this is a depth image + SpvWord ms = inst->isMultisample() ? isMultisampled : notMultisampled; + + SpvWord sampled = sampledUnknown; + switch(inst->getAccess()) + { + case SlangResourceAccess::SLANG_RESOURCE_ACCESS_READ_WRITE: + case SlangResourceAccess::SLANG_RESOURCE_ACCESS_RASTER_ORDERED: + sampled = readWriteImage; + break; + case SlangResourceAccess::SLANG_RESOURCE_ACCESS_NONE: + case SlangResourceAccess::SLANG_RESOURCE_ACCESS_READ: + sampled = sampledImage; + break; + } + + // TODO: we need to do as _emitGLSLImageFormatModifier does, + // take a guess at the image format + SpvImageFormat format = SpvImageFormatUnknown; + + // + // Capabilities, according to section 3.8 + // + // SPIR-V requires that the sampled/rw info on the image isn't unknown + SLANG_ASSERT(sampled == sampledImage || sampled == readWriteImage); + switch(dim) + { + case SpvDim1D: + requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampled1D : SpvCapabilityImage1D); + break; + case SpvDim2D: + // Also requires Shader or Kernel, but these are a given (?) + if(sampled == readWriteImage && ms == isMultisampled && arrayed == isArrayed) + requireSPIRVCapability(SpvCapabilityImageMSArray); + break; + case SpvDim3D: + break; + case SpvDimCube: + // Requires shader also + if(sampled == readWriteImage && arrayed == isArrayed) + requireSPIRVCapability(SpvCapabilityImageCubeArray); + break; + case SpvDimRect: + requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampledRect : SpvCapabilityImageRect); + break; + case SpvDimBuffer: + requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampledBuffer : SpvCapabilityImageBuffer); + break; + case SpvDimSubpassData: + requireSPIRVCapability(SpvCapabilityInputAttachment); + break; + case SpvDimTileImageDataEXT: + SLANG_UNIMPLEMENTED_X("OpTypeImage Capabilities for SpvDimTileImageDataEXT"); + break; + } + if(format == SpvImageFormatUnknown && sampled == readWriteImage) + { + // TODO: It may not be necessary to have both of these + // depending on if we read or write + requireSPIRVCapability(SpvCapabilityStorageImageReadWithoutFormat); + requireSPIRVCapability(SpvCapabilityStorageImageWriteWithoutFormat); + } + + // + // The op itself + // + return emitOpTypeImage( + assignee, + dropVector(sampledType), + dim, + SpvLiteralInteger::from32(depth), + SpvLiteralInteger::from32(arrayed), + SpvLiteralInteger::from32(ms), + SpvLiteralInteger::from32(sampled), + format + ); + } + // Ensures an SpvInst for the specified vector type is emitted. // `inst` represents an optional `IRVectorType` inst representing the vector type, if // it is nullptr, this function will create one. |
