Skip to content

Commit

Permalink
Return texture types from SPIR-V reflection
Browse files Browse the repository at this point in the history
Summary: Return texture type info from the reflection function

Reviewed By: corporateshark

Differential Revision: D49147291

fbshipit-source-id: 9b1a7427ee070e96258d576d19c74c3341d13c32
  • Loading branch information
ChristianK275 authored and facebook-github-bot committed Sep 21, 2023
1 parent 3979aa1 commit ffbaea1
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 18 deletions.
15 changes: 10 additions & 5 deletions src/igl/tests/vulkan/SpvReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,16 @@ TEST(SpvReflectionTest, TextureTest) {

ASSERT_EQ(spvModuleInfo.uniformBufferBindingLocations.size(), 0);
EXPECT_EQ(spvModuleInfo.storageBufferBindingLocations.size(), 0);
EXPECT_EQ(spvModuleInfo.textureBindingLocations.size(), 4);
EXPECT_EQ(spvModuleInfo.textureBindingLocations[0], kNoBindingLocation);
EXPECT_EQ(spvModuleInfo.textureBindingLocations[1], 1);
EXPECT_EQ(spvModuleInfo.textureBindingLocations[2], kNoBindingLocation);
EXPECT_EQ(spvModuleInfo.textureBindingLocations[3], 3);
EXPECT_EQ(spvModuleInfo.textures.size(), 4);
EXPECT_EQ(spvModuleInfo.textures[0].bindingLocation, kNoBindingLocation);
EXPECT_EQ(spvModuleInfo.textures[1].bindingLocation, 1);
EXPECT_EQ(spvModuleInfo.textures[2].bindingLocation, kNoBindingLocation);
EXPECT_EQ(spvModuleInfo.textures[3].bindingLocation, 3);

EXPECT_EQ(spvModuleInfo.textures[0].type, TextureType::TwoD);
EXPECT_EQ(spvModuleInfo.textures[1].type, TextureType::TwoD);
EXPECT_EQ(spvModuleInfo.textures[2].type, TextureType::TwoD);
EXPECT_EQ(spvModuleInfo.textures[3].type, TextureType::TwoD);
}

} // namespace igl::tests
90 changes: 78 additions & 12 deletions src/igl/vulkan/util/SpvReflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,17 @@ constexpr size_t kOpTypePointerId = 1;
constexpr size_t kOpTypePointerObjectTypeId = 3;
IGL_MAYBE_UNUSED constexpr size_t kOpTypePointerMaxUsedIx = kOpTypePointerObjectTypeId;

constexpr size_t kOpTypeImageTypeId = 1;
constexpr size_t kOpTypeImageDim = 3;
constexpr size_t kOpTypeImageArrayed = 5;
IGL_MAYBE_UNUSED constexpr size_t kOpTypeImageMaxUsedId = kOpTypeImageDim;

constexpr size_t kOpTypeSampledImageTypeId = 1;
IGL_MAYBE_UNUSED constexpr size_t kOpTypeSampledImageMaxUsedId = kOpTypeSampledImageTypeId;
constexpr size_t kOpTypeSampledImageImageTypeId = 2;
IGL_MAYBE_UNUSED constexpr size_t kOpTypeSampledImageMaxUsedId = kOpTypeSampledImageImageTypeId;

enum class OpCode : uint32_t {
OpTypeImage = 25,
OpTypeSampledImage = 27,
OpTypePointer = 32,
OpVariable = 59,
Expand All @@ -49,6 +56,17 @@ struct Decoration {
enum : uint32_t { Block = 2, Binding = 33 };
};

struct ImageDimensionality {
enum : uint32_t {
Dim1d = 0,
Dim2d = 1,
Dim3d = 2,
DimCube = 3,
DimRect = 4,
Dim2dExternal = 666, // Doesn't exist in SPIR-V, but needed for Android.
};
};

struct StorageClass {
enum : uint32_t { Uniform = 2, StorageBuffer = 12 };
};
Expand All @@ -63,6 +81,24 @@ OpCode getOpCode(uint32_t firstWord) {
return static_cast<OpCode>(firstWord & kSpvOpCodeMask);
}

TextureType getTextureType(uint32_t dim, bool isArrayed) {
switch (dim) {
case ImageDimensionality::Dim2d:
return isArrayed ? TextureType::TwoDArray : TextureType::TwoD;
case ImageDimensionality::Dim3d:
return TextureType::ThreeD;
case ImageDimensionality::DimCube:
return TextureType::Cube;
case ImageDimensionality::Dim2dExternal:
return TextureType::ExternalImage;

case ImageDimensionality::DimRect:
case ImageDimensionality::Dim1d:
default:
return TextureType::Invalid;
}
}

} // namespace

SpvModuleInfo getReflectionData(const uint32_t* words, size_t size) {
Expand All @@ -77,9 +113,10 @@ SpvModuleInfo getReflectionData(const uint32_t* words, size_t size) {

std::unordered_set<ResultId> interfaceBlockTypeIds;
std::unordered_set<ResultId> interfaceBlockPointerTypeIds;
std::unordered_set<ResultId> sampledImageTypeIds;
std::unordered_set<ResultId> sampledImagePointerTypeIds;
std::unordered_map<ResultId, ResultId> sampledImageTypeIdToImageTypeId;
std::unordered_map<ResultId, TextureType> sampledImagePointerTypeIds;
std::unordered_map<ResultId, uint32_t> bindingLocations;
std::unordered_map<ResultId, TextureType> imageTypes;

for (size_t pos = kSpvHeaderSize; pos < size;) {
uint16_t instructionSize = getInstructionSize(words[pos]);
Expand Down Expand Up @@ -107,12 +144,23 @@ SpvModuleInfo getReflectionData(const uint32_t* words, size_t size) {
break;
}

case OpCode::OpTypeImage: {
IGL_ASSERT_MSG((pos + kOpTypeImageMaxUsedId) < size, "OpTypeImage out of bounds");
ResultId imageTypeId = words[pos + kOpTypeImageTypeId];
uint32_t dim = words[pos + kOpTypeImageDim];
bool isArrayed = words[pos + kOpTypeImageArrayed] == 1u;
TextureType textureType = getTextureType(dim, isArrayed);
imageTypes.insert({imageTypeId, textureType});
break;
}

case OpCode::OpTypeSampledImage: {
IGL_ASSERT_MSG((pos + kOpTypeSampledImageMaxUsedId) < size,
"OpTypeSampledImage out of bounds");

ResultId sampledImageTypeId = words[pos + kOpTypeSampledImageTypeId];
sampledImageTypeIds.insert(sampledImageTypeId);
ResultId imageTypeId = words[pos + kOpTypeSampledImageImageTypeId];
sampledImageTypeIdToImageTypeId.insert({sampledImageTypeId, imageTypeId});
break;
}

Expand All @@ -123,8 +171,18 @@ SpvModuleInfo getReflectionData(const uint32_t* words, size_t size) {
ResultId pointerTypeId = words[pos + kOpTypePointerId];
if (interfaceBlockTypeIds.count(objectTypeId)) {
interfaceBlockPointerTypeIds.insert(pointerTypeId);
} else if (sampledImageTypeIds.count(objectTypeId)) {
sampledImagePointerTypeIds.insert(pointerTypeId);
} else {
auto sampledImageTypeIdToImageTypeIdIter =
sampledImageTypeIdToImageTypeId.find(objectTypeId);
if (sampledImageTypeIdToImageTypeIdIter != sampledImageTypeIdToImageTypeId.end()) {
auto imageTypeId = sampledImageTypeIdToImageTypeIdIter->second;
auto imageTypesIter = imageTypes.find(imageTypeId);
TextureType textureType = TextureType::Invalid;
if (imageTypesIter != imageTypes.end()) {
textureType = imageTypesIter->second;
}
sampledImagePointerTypeIds.insert({pointerTypeId, textureType});
}
}

break;
Expand All @@ -147,12 +205,20 @@ SpvModuleInfo getReflectionData(const uint32_t* words, size_t size) {
} else if (storageClass == StorageClass::StorageBuffer) {
spvModuleInfo.storageBufferBindingLocations.push_back(bindingLocation);
}
} else if (sampledImagePointerTypeIds.count(variableTypeId)) {
auto bindingLocationIt = bindingLocations.find(variableId);
uint32_t bindingLocation = bindingLocationIt != bindingLocations.end()
? bindingLocationIt->second
: kNoBindingLocation;
spvModuleInfo.textureBindingLocations.push_back(bindingLocation);
} else {
auto sampledImagePointerTypeIdsIter = sampledImagePointerTypeIds.find(variableTypeId);
if (sampledImagePointerTypeIdsIter != sampledImagePointerTypeIds.end()) {
auto bindingLocationIt = bindingLocations.find(variableId);
uint32_t bindingLocation = bindingLocationIt != bindingLocations.end()
? bindingLocationIt->second
: kNoBindingLocation;

auto textureType = sampledImagePointerTypeIdsIter->second;
TextureDescription textureDesc;
textureDesc.type = textureType;
textureDesc.bindingLocation = bindingLocation;
spvModuleInfo.textures.push_back(std::move(textureDesc));
}
}

break;
Expand Down
8 changes: 7 additions & 1 deletion src/igl/vulkan/util/SpvReflection.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,23 @@

#include <cstddef>
#include <cstdint>
#include <igl/Texture.h>
#include <limits>
#include <vector>

namespace igl::vulkan::util {

constexpr uint32_t kNoBindingLocation = std::numeric_limits<uint32_t>::max();

struct TextureDescription {
uint32_t bindingLocation = kNoBindingLocation;
TextureType type = TextureType::Invalid;
};

struct SpvModuleInfo {
std::vector<uint32_t> uniformBufferBindingLocations;
std::vector<uint32_t> storageBufferBindingLocations;
std::vector<uint32_t> textureBindingLocations;
std::vector<TextureDescription> textures;
};

SpvModuleInfo getReflectionData(const uint32_t* words, size_t size);
Expand Down

0 comments on commit ffbaea1

Please sign in to comment.