mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-08 19:40:06 +00:00
SPV: only declare the pure 8/16-bit capabilities when needed.
Only when operations stray outside the 8/16-bit storage-capabilities are the general (pure 8/16-bit) capabilities needed.
This commit is contained in:
parent
149afc3930
commit
31aa3d6019
@ -2612,7 +2612,6 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
||||
spvType = builder.makeFloatType(64);
|
||||
break;
|
||||
case glslang::EbtFloat16:
|
||||
builder.addCapability(spv::CapabilityFloat16);
|
||||
#if AMD_EXTENSIONS
|
||||
if (builder.getSpvVersion() < glslang::EShTargetSpv_1_3)
|
||||
builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
|
||||
@ -2627,16 +2626,13 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
||||
else
|
||||
spvType = builder.makeBoolType();
|
||||
break;
|
||||
case glslang::EbtInt8:
|
||||
builder.addCapability(spv::CapabilityInt8);
|
||||
case glslang::EbtInt8:
|
||||
spvType = builder.makeIntType(8);
|
||||
break;
|
||||
case glslang::EbtUint8:
|
||||
builder.addCapability(spv::CapabilityInt8);
|
||||
spvType = builder.makeUintType(8);
|
||||
break;
|
||||
case glslang::EbtInt16:
|
||||
builder.addCapability(spv::CapabilityInt16);
|
||||
case glslang::EbtInt16:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
if (builder.getSpvVersion() < glslang::EShTargetSpv_1_3)
|
||||
builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16);
|
||||
@ -2644,7 +2640,6 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
||||
spvType = builder.makeIntType(16);
|
||||
break;
|
||||
case glslang::EbtUint16:
|
||||
builder.addCapability(spv::CapabilityInt16);
|
||||
#ifdef AMD_EXTENSIONS
|
||||
if (builder.getSpvVersion() < glslang::EShTargetSpv_1_3)
|
||||
builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16);
|
||||
|
@ -194,10 +194,8 @@ Id Builder::makeIntegerType(int width, bool hasSign)
|
||||
// deal with capabilities
|
||||
switch (width) {
|
||||
case 8:
|
||||
addCapability(CapabilityInt8);
|
||||
break;
|
||||
case 16:
|
||||
addCapability(CapabilityInt16);
|
||||
// these are currently handled by storage-type declarations and post processing
|
||||
break;
|
||||
case 64:
|
||||
addCapability(CapabilityInt64);
|
||||
@ -229,7 +227,7 @@ Id Builder::makeFloatType(int width)
|
||||
// deal with capabilities
|
||||
switch (width) {
|
||||
case 16:
|
||||
addCapability(CapabilityFloat16);
|
||||
// currently handled by storage-type declarations and post processing
|
||||
break;
|
||||
case 64:
|
||||
addCapability(CapabilityFloat64);
|
||||
@ -520,12 +518,6 @@ Op Builder::getMostBasicTypeClass(Id typeId) const
|
||||
Op typeClass = instr->getOpCode();
|
||||
switch (typeClass)
|
||||
{
|
||||
case OpTypeVoid:
|
||||
case OpTypeBool:
|
||||
case OpTypeInt:
|
||||
case OpTypeFloat:
|
||||
case OpTypeStruct:
|
||||
return typeClass;
|
||||
case OpTypeVector:
|
||||
case OpTypeMatrix:
|
||||
case OpTypeArray:
|
||||
@ -534,8 +526,7 @@ Op Builder::getMostBasicTypeClass(Id typeId) const
|
||||
case OpTypePointer:
|
||||
return getMostBasicTypeClass(instr->getIdOperand(1));
|
||||
default:
|
||||
assert(0);
|
||||
return OpTypeFloat;
|
||||
return typeClass;
|
||||
}
|
||||
}
|
||||
|
||||
@ -622,6 +613,36 @@ Id Builder::getContainedTypeId(Id typeId) const
|
||||
return getContainedTypeId(typeId, 0);
|
||||
}
|
||||
|
||||
// Returns true if 'typeId' is or contains a scalar type declared with 'typeOp'
|
||||
// of width 'width'. The 'width' is only consumed for int and float types.
|
||||
// Returns false otherwise.
|
||||
bool Builder::containsType(Id typeId, spv::Op typeOp, int width) const
|
||||
{
|
||||
const Instruction& instr = *module.getInstruction(typeId);
|
||||
|
||||
Op typeClass = instr.getOpCode();
|
||||
switch (typeClass)
|
||||
{
|
||||
case OpTypeInt:
|
||||
case OpTypeFloat:
|
||||
return typeClass == typeOp && instr.getImmediateOperand(0) == width;
|
||||
case OpTypeStruct:
|
||||
for (int m = 0; m < instr.getNumOperands(); ++m) {
|
||||
if (containsType(instr.getIdOperand(m), typeOp, width))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case OpTypeVector:
|
||||
case OpTypeMatrix:
|
||||
case OpTypeArray:
|
||||
case OpTypeRuntimeArray:
|
||||
case OpTypePointer:
|
||||
return containsType(getContainedTypeId(typeId), typeOp, width);
|
||||
default:
|
||||
return typeClass == typeOp;
|
||||
}
|
||||
}
|
||||
|
||||
// See if a scalar constant of this type has already been created, so it
|
||||
// can be reused rather than duplicated. (Required by the specification).
|
||||
Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value)
|
||||
|
@ -167,6 +167,7 @@ public:
|
||||
bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
|
||||
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
|
||||
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
|
||||
bool containsType(Id typeId, Op typeOp, int width) const;
|
||||
|
||||
bool isConstantOpCode(Op opcode) const;
|
||||
bool isSpecConstantOpCode(Op opcode) const;
|
||||
@ -569,9 +570,11 @@ public:
|
||||
void postProcess();
|
||||
|
||||
// Hook to visit each instruction in a block in a function
|
||||
void postProcess(Instruction& inst);
|
||||
void postProcess(const Instruction&);
|
||||
// Hook to visit each instruction in a reachable block in a function.
|
||||
void postProcessReachable(Instruction& inst);
|
||||
void postProcessReachable(const Instruction&);
|
||||
// Hook to visit each non-32-bit sized float/int operation in a block.
|
||||
void postProcessType(const Instruction&, spv::Id typeId);
|
||||
|
||||
void dump(std::vector<unsigned int>&) const;
|
||||
|
||||
|
@ -61,8 +61,78 @@ namespace spv {
|
||||
|
||||
namespace spv {
|
||||
|
||||
// Hook to visit each operand type and result type of an instruction.
|
||||
// Will be called multiple times for one instruction, once for each typed
|
||||
// operand and the result.
|
||||
void Builder::postProcessType(const Instruction& inst, Id typeId)
|
||||
{
|
||||
// Characterize the type being questioned
|
||||
Id basicTypeOp = getMostBasicTypeClass(typeId);
|
||||
int width = 0;
|
||||
if (basicTypeOp == OpTypeFloat || basicTypeOp == OpTypeInt)
|
||||
width = getScalarTypeWidth(typeId);
|
||||
|
||||
// Do opcode-specific checks
|
||||
switch (inst.getOpCode()) {
|
||||
case OpLoad:
|
||||
case OpStore:
|
||||
if (basicTypeOp == OpTypeStruct) {
|
||||
if (containsType(typeId, OpTypeInt, 8))
|
||||
addCapability(CapabilityInt8);
|
||||
if (containsType(typeId, OpTypeInt, 16))
|
||||
addCapability(CapabilityInt16);
|
||||
if (containsType(typeId, OpTypeFloat, 16))
|
||||
addCapability(CapabilityFloat16);
|
||||
} else {
|
||||
StorageClass storageClass = getStorageClass(inst.getIdOperand(0));
|
||||
if (width == 8) {
|
||||
switch (storageClass) {
|
||||
case StorageClassUniform:
|
||||
case StorageClassStorageBuffer:
|
||||
case StorageClassPushConstant:
|
||||
break;
|
||||
default:
|
||||
addCapability(CapabilityInt8);
|
||||
break;
|
||||
}
|
||||
} else if (width == 16) {
|
||||
switch (storageClass) {
|
||||
case StorageClassUniform:
|
||||
case StorageClassStorageBuffer:
|
||||
case StorageClassPushConstant:
|
||||
case StorageClassInput:
|
||||
case StorageClassOutput:
|
||||
break;
|
||||
default:
|
||||
if (basicTypeOp == OpTypeInt)
|
||||
addCapability(CapabilityInt16);
|
||||
if (basicTypeOp == OpTypeFloat)
|
||||
addCapability(CapabilityFloat16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OpAccessChain:
|
||||
case OpPtrAccessChain:
|
||||
case OpCopyObject:
|
||||
case OpFConvert:
|
||||
case OpSConvert:
|
||||
case OpUConvert:
|
||||
break;
|
||||
default:
|
||||
if (basicTypeOp == OpTypeFloat && width == 16)
|
||||
addCapability(CapabilityFloat16);
|
||||
if (basicTypeOp == OpTypeInt && width == 16)
|
||||
addCapability(CapabilityInt16);
|
||||
if (basicTypeOp == OpTypeInt && width == 8)
|
||||
addCapability(CapabilityInt8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Called for each instruction that resides in a block.
|
||||
void Builder::postProcess(Instruction& inst)
|
||||
void Builder::postProcess(const Instruction& inst)
|
||||
{
|
||||
// Add capabilities based simply on the opcode.
|
||||
switch (inst.getOpCode()) {
|
||||
@ -104,10 +174,22 @@ void Builder::postProcess(Instruction& inst)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Checks based on type
|
||||
if (inst.getTypeId() != NoType)
|
||||
postProcessType(inst, inst.getTypeId());
|
||||
for (int op = 0; op < inst.getNumOperands(); ++op) {
|
||||
if (inst.isIdOperand(op)) {
|
||||
// In blocks, these are always result ids, but we are relying on
|
||||
// getTypeId() to return NoType for things like OpLabel.
|
||||
if (getTypeId(inst.getIdOperand(op)) != NoType)
|
||||
postProcessType(inst, getTypeId(inst.getIdOperand(op)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called for each instruction in a reachable block.
|
||||
void Builder::postProcessReachable(Instruction& inst)
|
||||
void Builder::postProcessReachable(const Instruction& inst)
|
||||
{
|
||||
// did have code here, but questionable to do so without deleting the instructions
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ public:
|
||||
addImmediateOperand(word);
|
||||
}
|
||||
}
|
||||
bool isIdOperand(int op) { return idOperand[op]; }
|
||||
bool isIdOperand(int op) const { return idOperand[op]; }
|
||||
void setBlock(Block* b) { block = b; }
|
||||
Block* getBlock() const { return block; }
|
||||
Op getOpCode() const { return opCode; }
|
||||
|
@ -4,7 +4,6 @@ spv.16bitstorage-int.frag
|
||||
// Id's are bound by 171
|
||||
|
||||
Capability Shader
|
||||
Capability Int16
|
||||
Capability StorageUniformBufferBlock16
|
||||
Capability StorageUniform16
|
||||
Extension "SPV_AMD_gpu_shader_int16"
|
||||
|
@ -4,7 +4,6 @@ spv.16bitstorage-uint.frag
|
||||
// Id's are bound by 173
|
||||
|
||||
Capability Shader
|
||||
Capability Int16
|
||||
Capability StorageUniformBufferBlock16
|
||||
Capability StorageUniform16
|
||||
Extension "SPV_AMD_gpu_shader_int16"
|
||||
|
@ -4,7 +4,6 @@ spv.16bitstorage.frag
|
||||
// Id's are bound by 173
|
||||
|
||||
Capability Shader
|
||||
Capability Float16
|
||||
Capability StorageUniformBufferBlock16
|
||||
Capability StorageUniform16
|
||||
Extension "SPV_AMD_gpu_shader_half_float"
|
||||
|
@ -4,7 +4,6 @@ spv.8bitstorage-int.frag
|
||||
// Id's are bound by 171
|
||||
|
||||
Capability Shader
|
||||
Capability Int8
|
||||
Capability CapabilityStorageBuffer8BitAccess
|
||||
Capability CapabilityUniformAndStorageBuffer8BitAccess
|
||||
Extension "SPV_KHR_8bit_storage"
|
||||
|
@ -4,7 +4,6 @@ spv.8bitstorage-uint.frag
|
||||
// Id's are bound by 173
|
||||
|
||||
Capability Shader
|
||||
Capability Int8
|
||||
Capability CapabilityStorageBuffer8BitAccess
|
||||
Capability CapabilityUniformAndStorageBuffer8BitAccess
|
||||
Extension "SPV_KHR_8bit_storage"
|
||||
|
Loading…
Reference in New Issue
Block a user