Skip to content

Commit 359fdc9

Browse files
Handle combined image and samplers in spirv (shader-slang#3213)
* Handle combined image and samplers in spirv * less expected failure --------- Co-authored-by: Yong He <yonghe@outlook.com>
1 parent da30696 commit 359fdc9

File tree

3 files changed

+152
-138
lines changed

3 files changed

+152
-138
lines changed

source/slang/slang-emit-spirv-ops.h

+9
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,15 @@ SpvInst* emitOpTypeSampler(IRInst* inst)
229229
);
230230
}
231231

232+
// https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeSampler
233+
template<typename T1>
234+
SpvInst* emitOpTypeSampledImage(IRInst* inst, const T1& imageType)
235+
{
236+
return emitInstMemoized(
237+
getSection(SpvLogicalSectionID::ConstantsAndTypes), inst, SpvOpTypeSampledImage, kResultID, imageType
238+
);
239+
}
240+
232241
SpvInst* emitOpTypeAccelerationStructure(IRInst* inst)
233242
{
234243
return emitInstMemoized(

source/slang/slang-emit-spirv.cpp

+143-136
Original file line numberDiff line numberDiff line change
@@ -1314,144 +1314,14 @@ struct SPIRVEmitContext
13141314
return arrayType;
13151315
}
13161316
case kIROp_TextureType:
1317-
{
1318-
// Some untyped constants from OpTypeImage
1319-
// https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage
1320-
1321-
// indicates not a depth image
1322-
[[maybe_unused]]
1323-
const SpvWord notDepthImage = 0;
1324-
// indicates a depth image
1325-
[[maybe_unused]]
1326-
const SpvWord isDepthImage = 1;
1327-
// means no indication as to whether this is a depth or non-depth image
1328-
const SpvWord unknownDepthImage = 2;
1329-
1330-
// indicates non-arrayed content
1331-
const SpvWord notArrayed = 0;
1332-
// indicates arrayed content
1333-
const SpvWord isArrayed = 1;
1334-
1335-
// indicates single-sampled content
1336-
const SpvWord notMultisampled = 0;
1337-
// indicates multisampled content
1338-
const SpvWord isMultisampled = 1;
1339-
1340-
// indicates this is only known at run time, not at compile time
1341-
const SpvWord sampledUnknown = 0;
1342-
// indicates an image compatible with sampling operations
1343-
const SpvWord sampledImage = 1;
1344-
// indicates an image compatible with read/write operations (a storage or subpass data image).
1345-
const SpvWord readWriteImage = 2;
1346-
1347-
//
1348-
1349-
const auto texTypeInst = as<IRTextureType>(inst);
1350-
const auto sampledType = texTypeInst->getElementType();
1351-
SpvDim dim = SpvDim1D; // Silence uninitialized warnings from msvc...
1352-
switch(texTypeInst->GetBaseShape())
1353-
{
1354-
case TextureFlavor::Shape1D:
1355-
case TextureFlavor::Shape1DArray:
1356-
dim = SpvDim1D;
1357-
break;
1358-
case TextureFlavor::Shape2D:
1359-
case TextureFlavor::Shape2DArray:
1360-
dim = SpvDim2D;
1361-
break;
1362-
case TextureFlavor::Shape3D:
1363-
dim = SpvDim3D;
1364-
break;
1365-
case TextureFlavor::ShapeCube:
1366-
case TextureFlavor::ShapeCubeArray:
1367-
dim = SpvDimCube;
1368-
break;
1369-
case TextureFlavor::ShapeBuffer:
1370-
dim = SpvDimBuffer;
1371-
break;
1372-
}
1373-
SpvWord arrayed = texTypeInst->isArray() ? isArrayed : notArrayed;
1374-
1375-
// Vulkan spec 16.1: "The “Depth” operand of OpTypeImage is ignored."
1376-
SpvWord depth = unknownDepthImage; // No knowledge of if this is a depth image
1377-
SpvWord ms = texTypeInst->isMultisample() ? isMultisampled : notMultisampled;
1378-
1379-
SpvWord sampled = sampledUnknown;
1380-
switch(texTypeInst->getAccess())
1381-
{
1382-
case SlangResourceAccess::SLANG_RESOURCE_ACCESS_READ_WRITE:
1383-
case SlangResourceAccess::SLANG_RESOURCE_ACCESS_RASTER_ORDERED:
1384-
sampled = readWriteImage;
1385-
break;
1386-
case SlangResourceAccess::SLANG_RESOURCE_ACCESS_NONE:
1387-
case SlangResourceAccess::SLANG_RESOURCE_ACCESS_READ:
1388-
sampled = sampledImage;
1389-
break;
1390-
}
1391-
1392-
// TODO: we need to do as _emitGLSLImageFormatModifier does,
1393-
// take a guess at the image format
1394-
SpvImageFormat format = SpvImageFormatUnknown;
1395-
1396-
//
1397-
// Capabilities, according to section 3.8
1398-
//
1399-
// SPIR-V requires that the sampled/rw info on the image isn't unknown
1400-
SLANG_ASSERT(sampled == sampledImage || sampled == readWriteImage);
1401-
switch(dim)
1402-
{
1403-
case SpvDim1D:
1404-
requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampled1D : SpvCapabilityImage1D);
1405-
break;
1406-
case SpvDim2D:
1407-
// Also requires Shader or Kernel, but these are a given (?)
1408-
if(sampled == readWriteImage && ms == isMultisampled && arrayed == isArrayed)
1409-
requireSPIRVCapability(SpvCapabilityImageMSArray);
1410-
break;
1411-
case SpvDim3D:
1412-
break;
1413-
case SpvDimCube:
1414-
// Requires shader also
1415-
if(sampled == readWriteImage && arrayed == isArrayed)
1416-
requireSPIRVCapability(SpvCapabilityImageCubeArray);
1417-
break;
1418-
case SpvDimRect:
1419-
requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampledRect : SpvCapabilityImageRect);
1420-
break;
1421-
case SpvDimBuffer:
1422-
requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampledBuffer : SpvCapabilityImageBuffer);
1423-
break;
1424-
case SpvDimSubpassData:
1425-
requireSPIRVCapability(SpvCapabilityInputAttachment);
1426-
break;
1427-
case SpvDimTileImageDataEXT:
1428-
SLANG_UNIMPLEMENTED_X("OpTypeImage Capabilities for SpvDimTileImageDataEXT");
1429-
break;
1430-
}
1431-
if(format == SpvImageFormatUnknown && sampled == readWriteImage)
1432-
{
1433-
// TODO: It may not be necessary to have both of these
1434-
// depending on if we read or write
1435-
requireSPIRVCapability(SpvCapabilityStorageImageReadWithoutFormat);
1436-
requireSPIRVCapability(SpvCapabilityStorageImageWriteWithoutFormat);
1437-
}
1438-
1439-
//
1440-
// The op itself
1441-
//
1442-
return emitOpTypeImage(
1443-
inst,
1444-
dropVector(sampledType),
1445-
dim,
1446-
SpvLiteralInteger::from32(depth),
1447-
SpvLiteralInteger::from32(arrayed),
1448-
SpvLiteralInteger::from32(ms),
1449-
SpvLiteralInteger::from32(sampled),
1450-
format
1451-
);
1452-
}
1317+
return ensureTextureType(inst, cast<IRTextureType>(inst));
14531318
case kIROp_SamplerStateType:
14541319
return emitOpTypeSampler(inst);
1320+
case kIROp_TextureSamplerType:
1321+
return emitOpTypeSampledImage(
1322+
inst,
1323+
ensureTextureType(nullptr, cast<IRTextureTypeBase>(inst))
1324+
);
14551325

14561326
case kIROp_RaytracingAccelerationStructureType:
14571327
requireSPIRVCapability(SpvCapabilityRayTracingKHR);
@@ -1584,6 +1454,143 @@ struct SPIRVEmitContext
15841454
}
15851455
}
15861456

1457+
SpvInst* ensureTextureType(IRInst* assignee, IRTextureTypeBase* inst)
1458+
{
1459+
// Some untyped constants from OpTypeImage
1460+
// https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage
1461+
1462+
// indicates not a depth image
1463+
[[maybe_unused]]
1464+
const SpvWord notDepthImage = 0;
1465+
// indicates a depth image
1466+
[[maybe_unused]]
1467+
const SpvWord isDepthImage = 1;
1468+
// means no indication as to whether this is a depth or non-depth image
1469+
const SpvWord unknownDepthImage = 2;
1470+
1471+
// indicates non-arrayed content
1472+
const SpvWord notArrayed = 0;
1473+
// indicates arrayed content
1474+
const SpvWord isArrayed = 1;
1475+
1476+
// indicates single-sampled content
1477+
const SpvWord notMultisampled = 0;
1478+
// indicates multisampled content
1479+
const SpvWord isMultisampled = 1;
1480+
1481+
// indicates this is only known at run time, not at compile time
1482+
const SpvWord sampledUnknown = 0;
1483+
// indicates an image compatible with sampling operations
1484+
const SpvWord sampledImage = 1;
1485+
// indicates an image compatible with read/write operations (a storage or subpass data image).
1486+
const SpvWord readWriteImage = 2;
1487+
1488+
//
1489+
1490+
const auto sampledType = inst->getElementType();
1491+
SpvDim dim = SpvDim1D; // Silence uninitialized warnings from msvc...
1492+
switch(inst->GetBaseShape())
1493+
{
1494+
case TextureFlavor::Shape1D:
1495+
case TextureFlavor::Shape1DArray:
1496+
dim = SpvDim1D;
1497+
break;
1498+
case TextureFlavor::Shape2D:
1499+
case TextureFlavor::Shape2DArray:
1500+
dim = SpvDim2D;
1501+
break;
1502+
case TextureFlavor::Shape3D:
1503+
dim = SpvDim3D;
1504+
break;
1505+
case TextureFlavor::ShapeCube:
1506+
case TextureFlavor::ShapeCubeArray:
1507+
dim = SpvDimCube;
1508+
break;
1509+
case TextureFlavor::ShapeBuffer:
1510+
dim = SpvDimBuffer;
1511+
break;
1512+
}
1513+
SpvWord arrayed = inst->isArray() ? isArrayed : notArrayed;
1514+
1515+
// Vulkan spec 16.1: "The “Depth” operand of OpTypeImage is ignored."
1516+
SpvWord depth = unknownDepthImage; // No knowledge of if this is a depth image
1517+
SpvWord ms = inst->isMultisample() ? isMultisampled : notMultisampled;
1518+
1519+
SpvWord sampled = sampledUnknown;
1520+
switch(inst->getAccess())
1521+
{
1522+
case SlangResourceAccess::SLANG_RESOURCE_ACCESS_READ_WRITE:
1523+
case SlangResourceAccess::SLANG_RESOURCE_ACCESS_RASTER_ORDERED:
1524+
sampled = readWriteImage;
1525+
break;
1526+
case SlangResourceAccess::SLANG_RESOURCE_ACCESS_NONE:
1527+
case SlangResourceAccess::SLANG_RESOURCE_ACCESS_READ:
1528+
sampled = sampledImage;
1529+
break;
1530+
}
1531+
1532+
// TODO: we need to do as _emitGLSLImageFormatModifier does,
1533+
// take a guess at the image format
1534+
SpvImageFormat format = SpvImageFormatUnknown;
1535+
1536+
//
1537+
// Capabilities, according to section 3.8
1538+
//
1539+
// SPIR-V requires that the sampled/rw info on the image isn't unknown
1540+
SLANG_ASSERT(sampled == sampledImage || sampled == readWriteImage);
1541+
switch(dim)
1542+
{
1543+
case SpvDim1D:
1544+
requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampled1D : SpvCapabilityImage1D);
1545+
break;
1546+
case SpvDim2D:
1547+
// Also requires Shader or Kernel, but these are a given (?)
1548+
if(sampled == readWriteImage && ms == isMultisampled && arrayed == isArrayed)
1549+
requireSPIRVCapability(SpvCapabilityImageMSArray);
1550+
break;
1551+
case SpvDim3D:
1552+
break;
1553+
case SpvDimCube:
1554+
// Requires shader also
1555+
if(sampled == readWriteImage && arrayed == isArrayed)
1556+
requireSPIRVCapability(SpvCapabilityImageCubeArray);
1557+
break;
1558+
case SpvDimRect:
1559+
requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampledRect : SpvCapabilityImageRect);
1560+
break;
1561+
case SpvDimBuffer:
1562+
requireSPIRVCapability(sampled == sampledImage ? SpvCapabilitySampledBuffer : SpvCapabilityImageBuffer);
1563+
break;
1564+
case SpvDimSubpassData:
1565+
requireSPIRVCapability(SpvCapabilityInputAttachment);
1566+
break;
1567+
case SpvDimTileImageDataEXT:
1568+
SLANG_UNIMPLEMENTED_X("OpTypeImage Capabilities for SpvDimTileImageDataEXT");
1569+
break;
1570+
}
1571+
if(format == SpvImageFormatUnknown && sampled == readWriteImage)
1572+
{
1573+
// TODO: It may not be necessary to have both of these
1574+
// depending on if we read or write
1575+
requireSPIRVCapability(SpvCapabilityStorageImageReadWithoutFormat);
1576+
requireSPIRVCapability(SpvCapabilityStorageImageWriteWithoutFormat);
1577+
}
1578+
1579+
//
1580+
// The op itself
1581+
//
1582+
return emitOpTypeImage(
1583+
assignee,
1584+
dropVector(sampledType),
1585+
dim,
1586+
SpvLiteralInteger::from32(depth),
1587+
SpvLiteralInteger::from32(arrayed),
1588+
SpvLiteralInteger::from32(ms),
1589+
SpvLiteralInteger::from32(sampled),
1590+
format
1591+
);
1592+
}
1593+
15871594
// Ensures an SpvInst for the specified vector type is emitted.
15881595
// `inst` represents an optional `IRVectorType` inst representing the vector type, if
15891596
// it is nullptr, this function will create one.

tests/expected-failure.txt

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
tests/optimization/func-resource-result/func-resource-result-complex.slang.1 (vk)
2-
tests/type/texture-sampler/texture-sampler-2d.slang (vk)
3-
tests/hlsl-intrinsic/texture-lod-shadow.slang.1
42
tests/pipeline/rasterization/mesh/task-groupshared.slang.1 (vk)
53
tests/pipeline/rasterization/mesh/task-simple.slang.1 (vk)
64
tests/pipeline/rasterization/mesh/simple.slang.1 (vk)

0 commit comments

Comments
 (0)