Reland "Use op cache when emitting types."
This is a reland of commit 60ff0facbf
Structs are now deduplicated using a [Type*, SpvId] map.
Original change's description:
> Use op cache when emitting types.
>
> We no longer need to maintain a separate `fTypeMap` for mapping types
> to SpvIds, since the op cache handles this automatically.
>
> We also now support deduplicating instructions that don't have a result,
> such as decorations. (In particular, we needed to avoid emitting the
> SpvDecorationArrayStride op every time the array type was accessed, but
> this op doesn't have a result ID.)
>
> Change-Id: I779b8c8e3de5973b8f487b28c0a8ece9a1041845
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/529732
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: John Stiles <johnstiles@google.com>
> Auto-Submit: John Stiles <johnstiles@google.com>
Change-Id: I9f6a78d58e8af38a1fd690a8860d8b5aa3193be6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/529748
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
5977429087
commit
0688ea21b2
@ -83,7 +83,6 @@ bool SPIRVCodeGenerator::Instruction::operator==(const SPIRVCodeGenerator::Instr
|
||||
return fOp == that.fOp &&
|
||||
fResultKind == that.fResultKind &&
|
||||
fWords == that.fWords;
|
||||
|
||||
}
|
||||
|
||||
struct SPIRVCodeGenerator::Instruction::Hash {
|
||||
@ -103,6 +102,7 @@ struct SPIRVCodeGenerator::Word {
|
||||
kNumber,
|
||||
kDefaultPrecisionResult,
|
||||
kRelaxedPrecisionResult,
|
||||
kUncachedResult,
|
||||
};
|
||||
|
||||
Word(SpvId id) : fValue(id), fKind(Kind::kSpvId) {}
|
||||
@ -122,6 +122,10 @@ struct SPIRVCodeGenerator::Word {
|
||||
return Word{(int32_t)NA, kind};
|
||||
}
|
||||
|
||||
static Word UncachedResult() {
|
||||
return Word{(int32_t)NA, kUncachedResult};
|
||||
}
|
||||
|
||||
static Word Result() {
|
||||
return Word{(int32_t)NA, kDefaultPrecisionResult};
|
||||
}
|
||||
@ -515,10 +519,9 @@ void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t
|
||||
this->writeWord(word8, out);
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode,
|
||||
const SkTArray<Word>& words,
|
||||
OutputStream& out) {
|
||||
// Build up an cache key for this word.
|
||||
SPIRVCodeGenerator::Instruction SPIRVCodeGenerator::BuildInstructionKey(
|
||||
SpvOp_ opCode, const SkTArray<Word>& words) {
|
||||
// Assemble a cache key for this instruction.
|
||||
Instruction key;
|
||||
key.fOp = opCode;
|
||||
key.fWords.resize(words.count());
|
||||
@ -533,13 +536,33 @@ SpvId SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode,
|
||||
}
|
||||
}
|
||||
|
||||
SpvId result = NA;
|
||||
return key;
|
||||
}
|
||||
|
||||
if (key.fResultKind != Word::Kind::kNone) {
|
||||
SpvId SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode,
|
||||
const SkTArray<Word>& words,
|
||||
OutputStream& out) {
|
||||
// If this instruction exists in our op cache, return the cached SpvId.
|
||||
Instruction key = BuildInstructionKey(opCode, words);
|
||||
if (SpvId* cachedOp = fOpCache.find(key)) {
|
||||
return *cachedOp;
|
||||
}
|
||||
|
||||
SpvId result = NA;
|
||||
|
||||
switch (key.fResultKind) {
|
||||
case Word::Kind::kUncachedResult:
|
||||
// The instruction returns a SpvId, but we do not want caching or deduplication.
|
||||
result = fIdCount++;
|
||||
break;
|
||||
|
||||
case Word::Kind::kNone:
|
||||
// The instruction doesn't return a SpvId, but we can still cache and deduplicate it.
|
||||
fOpCache.set(key, result);
|
||||
break;
|
||||
|
||||
case Word::Kind::kDefaultPrecisionResult:
|
||||
case Word::Kind::kRelaxedPrecisionResult:
|
||||
// Consume a new SpvId and cache the instruction.
|
||||
result = fIdCount++;
|
||||
fOpCache.set(key, result);
|
||||
@ -554,6 +577,11 @@ SpvId SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode,
|
||||
this->writeInstruction(SpvOpDecorate, result, SpvDecorationRelaxedPrecision,
|
||||
fDecorationBuffer);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SkDEBUGFAIL("unexpected result kind");
|
||||
break;
|
||||
}
|
||||
|
||||
// Write the requested instruction.
|
||||
@ -750,27 +778,30 @@ SpvId SPIRVCodeGenerator::nextId(Precision precision) {
|
||||
return fIdCount++;
|
||||
}
|
||||
|
||||
void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memoryLayout,
|
||||
SpvId resultId) {
|
||||
this->writeInstruction(SpvOpName, resultId, type.name(), fNameBuffer);
|
||||
// go ahead and write all of the field types, so we don't inadvertently write them while we're
|
||||
// in the middle of writing the struct instruction
|
||||
std::vector<SpvId> types;
|
||||
SpvId SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memoryLayout) {
|
||||
// If we've already written out this struct, return its existing SpvId.
|
||||
if (SpvId* cachedStructId = fStructMap.find(&type)) {
|
||||
return *cachedStructId;
|
||||
}
|
||||
|
||||
// Write all of the field types first, so we don't inadvertently write them while we're in the
|
||||
// middle of writing the struct instruction.
|
||||
Words words;
|
||||
words.push_back(Word::UncachedResult());
|
||||
for (const auto& f : type.fields()) {
|
||||
types.push_back(this->getType(*f.fType, memoryLayout));
|
||||
}
|
||||
this->writeOpCode(SpvOpTypeStruct, 2 + (int32_t) types.size(), fConstantBuffer);
|
||||
this->writeWord(resultId, fConstantBuffer);
|
||||
for (SpvId id : types) {
|
||||
this->writeWord(id, fConstantBuffer);
|
||||
words.push_back(this->getType(*f.fType, memoryLayout));
|
||||
}
|
||||
SpvId resultId = this->writeInstruction(SpvOpTypeStruct, words, fConstantBuffer);
|
||||
this->writeInstruction(SpvOpName, resultId, type.name(), fNameBuffer);
|
||||
fStructMap.set(&type, resultId);
|
||||
|
||||
size_t offset = 0;
|
||||
for (int32_t i = 0; i < (int32_t) type.fields().size(); i++) {
|
||||
const Type::Field& field = type.fields()[i];
|
||||
if (!MemoryLayout::LayoutIsSupported(*field.fType)) {
|
||||
fContext.fErrors->error(type.fPosition, "type '" + field.fType->displayName() +
|
||||
"' is not permitted here");
|
||||
return;
|
||||
return resultId;
|
||||
}
|
||||
size_t size = memoryLayout.size(*field.fType);
|
||||
size_t alignment = memoryLayout.alignment(*field.fType);
|
||||
@ -814,6 +845,8 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor
|
||||
offset += alignment - offset % alignment;
|
||||
}
|
||||
}
|
||||
|
||||
return resultId;
|
||||
}
|
||||
|
||||
const Type& SPIRVCodeGenerator::getActualType(const Type& type) {
|
||||
@ -845,132 +878,105 @@ SpvId SPIRVCodeGenerator::getType(const Type& type) {
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layout) {
|
||||
const Type* type;
|
||||
std::unique_ptr<Type> arrayType;
|
||||
std::string arrayName;
|
||||
const Type* type = &rawType;
|
||||
|
||||
if (rawType.isArray()) {
|
||||
// For arrays, we need to synthesize a temporary Array type using the "actual" component
|
||||
// type. That is, if `short[10]` is passed in, we need to synthesize a `int[10]` Type.
|
||||
// Otherwise, we can end up with two different SpvIds for the same array type.
|
||||
const Type& component = this->getActualType(rawType.componentType());
|
||||
arrayName = component.getArrayName(rawType.columns());
|
||||
arrayType = Type::MakeArrayType(arrayName, component, rawType.columns());
|
||||
type = arrayType.get();
|
||||
} else {
|
||||
// For non-array types, we can simply look up the "actual" type and use it.
|
||||
type = &this->getActualType(rawType);
|
||||
}
|
||||
|
||||
std::string key(type->name());
|
||||
if (type->isStruct() || type->isArray()) {
|
||||
key += std::to_string(layout.fStd);
|
||||
#ifdef SK_DEBUG
|
||||
SkASSERT(layout.fStd == MemoryLayout::Standard::k140_Standard ||
|
||||
layout.fStd == MemoryLayout::Standard::k430_Standard);
|
||||
MemoryLayout::Standard otherStd = layout.fStd == MemoryLayout::Standard::k140_Standard
|
||||
? MemoryLayout::Standard::k430_Standard
|
||||
: MemoryLayout::Standard::k140_Standard;
|
||||
std::string otherKey = type->displayName() + std::to_string(otherStd);
|
||||
SkASSERT(!fTypeMap.find(otherKey));
|
||||
#endif
|
||||
}
|
||||
SpvId* entry = fTypeMap.find(key);
|
||||
if (!entry) {
|
||||
SpvId result = this->nextId(nullptr);
|
||||
switch (type->typeKind()) {
|
||||
case Type::TypeKind::kScalar:
|
||||
if (type->isBoolean()) {
|
||||
this->writeInstruction(SpvOpTypeBool, result, fConstantBuffer);
|
||||
} else if (type->isSigned()) {
|
||||
this->writeInstruction(SpvOpTypeInt, result, 32, 1, fConstantBuffer);
|
||||
} else if (type->isUnsigned()) {
|
||||
this->writeInstruction(SpvOpTypeInt, result, 32, 0, fConstantBuffer);
|
||||
} else if (type->isFloat()) {
|
||||
this->writeInstruction(SpvOpTypeFloat, result, 32, fConstantBuffer);
|
||||
} else {
|
||||
SkDEBUGFAILF("unrecognized scalar type '%s'", type->description().c_str());
|
||||
case Type::TypeKind::kVoid: {
|
||||
return this->writeInstruction(SpvOpTypeVoid, {Word::Result()}, fConstantBuffer);
|
||||
}
|
||||
break;
|
||||
case Type::TypeKind::kVector:
|
||||
this->writeInstruction(SpvOpTypeVector, result,
|
||||
this->getType(type->componentType(), layout),
|
||||
type->columns(), fConstantBuffer);
|
||||
break;
|
||||
case Type::TypeKind::kMatrix:
|
||||
this->writeInstruction(
|
||||
SpvOpTypeMatrix,
|
||||
result,
|
||||
this->getType(IndexExpression::IndexType(fContext, *type), layout),
|
||||
type->columns(),
|
||||
case Type::TypeKind::kScalar:
|
||||
case Type::TypeKind::kLiteral: {
|
||||
if (type->isBoolean()) {
|
||||
return this->writeInstruction(SpvOpTypeBool, {Word::Result()}, fConstantBuffer);
|
||||
}
|
||||
if (type->isSigned()) {
|
||||
return this->writeInstruction(SpvOpTypeInt,
|
||||
{Word::Result(), Word::Number(32), Word::Number(1)},
|
||||
fConstantBuffer);
|
||||
break;
|
||||
case Type::TypeKind::kStruct:
|
||||
this->writeStruct(*type, layout, result);
|
||||
break;
|
||||
}
|
||||
if (type->isUnsigned()) {
|
||||
return this->writeInstruction(SpvOpTypeInt,
|
||||
{Word::Result(), Word::Number(32), Word::Number(0)},
|
||||
fConstantBuffer);
|
||||
}
|
||||
if (type->isFloat()) {
|
||||
return this->writeInstruction(SpvOpTypeFloat,
|
||||
{Word::Result(), Word::Number(32)},
|
||||
fConstantBuffer);
|
||||
}
|
||||
SkDEBUGFAILF("unrecognized scalar type '%s'", type->description().c_str());
|
||||
return (SpvId)-1;
|
||||
}
|
||||
case Type::TypeKind::kVector: {
|
||||
SpvId scalarTypeId = this->getType(type->componentType(), layout);
|
||||
return this->writeInstruction(
|
||||
SpvOpTypeVector,
|
||||
{Word::Result(), scalarTypeId, Word::Number(type->columns())},
|
||||
fConstantBuffer);
|
||||
}
|
||||
case Type::TypeKind::kMatrix: {
|
||||
SpvId vectorTypeId = this->getType(IndexExpression::IndexType(fContext, *type), layout);
|
||||
return this->writeInstruction(
|
||||
SpvOpTypeMatrix,
|
||||
{Word::Result(), vectorTypeId, Word::Number(type->columns())},
|
||||
fConstantBuffer);
|
||||
}
|
||||
case Type::TypeKind::kArray: {
|
||||
if (!MemoryLayout::LayoutIsSupported(*type)) {
|
||||
fContext.fErrors->error(type->fPosition, "type '" + type->displayName() +
|
||||
"' is not permitted here");
|
||||
return this->nextId(nullptr);
|
||||
return NA;
|
||||
}
|
||||
if (type->columns() == 0) {
|
||||
// We do not support runtime-sized arrays.
|
||||
fContext.fErrors->error(type->fPosition, "runtime-sized arrays are not supported");
|
||||
return NA;
|
||||
}
|
||||
if (type->columns() > 0) {
|
||||
SpvId typeId = this->getType(type->componentType(), layout);
|
||||
SpvId countId = this->writeLiteral(type->columns(), *fContext.fTypes.fInt);
|
||||
this->writeInstruction(SpvOpTypeArray, result, typeId, countId,
|
||||
SpvId result = this->writeInstruction(SpvOpTypeArray, {Word::Result(), typeId, countId},
|
||||
fConstantBuffer);
|
||||
this->writeInstruction(SpvOpDecorate, result, SpvDecorationArrayStride,
|
||||
(int32_t) layout.stride(*type),
|
||||
fDecorationBuffer);
|
||||
} else {
|
||||
// We shouldn't have any runtime-sized arrays right now
|
||||
fContext.fErrors->error(type->fPosition,
|
||||
"runtime-sized arrays are not supported in SPIR-V");
|
||||
this->writeInstruction(SpvOpTypeRuntimeArray, result,
|
||||
this->getType(type->componentType(), layout),
|
||||
fConstantBuffer);
|
||||
this->writeInstruction(SpvOpDecorate, result, SpvDecorationArrayStride,
|
||||
(int32_t) layout.stride(*type),
|
||||
this->writeInstruction(
|
||||
SpvOpDecorate,
|
||||
{result, SpvDecorationArrayStride, Word::Number(layout.stride(*type))},
|
||||
fDecorationBuffer);
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
case Type::TypeKind::kStruct: {
|
||||
return this->writeStruct(*type, layout);
|
||||
}
|
||||
case Type::TypeKind::kSeparateSampler: {
|
||||
return this->writeInstruction(SpvOpTypeSampler, {Word::Result()}, fConstantBuffer);
|
||||
}
|
||||
case Type::TypeKind::kSampler: {
|
||||
// Subpass inputs should use the Texture type, not a Sampler.
|
||||
SkASSERT(type->dimensions() != SpvDimSubpassData);
|
||||
if (type->dimensions() == SpvDimBuffer) {
|
||||
if (SpvDimBuffer == type->dimensions()) {
|
||||
fCapabilities |= 1ULL << SpvCapabilitySampledBuffer;
|
||||
}
|
||||
SpvId imageTypeId = this->getType(type->textureType(), layout);
|
||||
this->writeInstruction(SpvOpTypeSampledImage, result, imageTypeId,
|
||||
return this->writeInstruction(SpvOpTypeSampledImage,
|
||||
{Word::Result(), imageTypeId},
|
||||
fConstantBuffer);
|
||||
break;
|
||||
}
|
||||
case Type::TypeKind::kSeparateSampler: {
|
||||
this->writeInstruction(SpvOpTypeSampler, result, fConstantBuffer);
|
||||
break;
|
||||
}
|
||||
case Type::TypeKind::kTexture: {
|
||||
this->writeInstruction(SpvOpTypeImage, result,
|
||||
this->getType(*fContext.fTypes.fFloat, layout),
|
||||
type->dimensions(), type->isDepth(),
|
||||
type->isArrayedTexture(), type->isMultisampled(),
|
||||
type->isSampled() ? 1 : 2, SpvImageFormatUnknown,
|
||||
SpvId floatTypeId = this->getType(*fContext.fTypes.fFloat, layout);
|
||||
return this->writeInstruction(SpvOpTypeImage,
|
||||
{Word::Result(),
|
||||
floatTypeId,
|
||||
Word::Number(type->dimensions()),
|
||||
Word::Number(type->isDepth()),
|
||||
Word::Number(type->isArrayedTexture()),
|
||||
Word::Number(type->isMultisampled()),
|
||||
Word::Number(type->isSampled() ? 1 : 2),
|
||||
SpvImageFormatUnknown},
|
||||
fConstantBuffer);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (type->isVoid()) {
|
||||
this->writeInstruction(SpvOpTypeVoid, result, fConstantBuffer);
|
||||
} else {
|
||||
default: {
|
||||
SkDEBUGFAILF("invalid type: %s", type->description().c_str());
|
||||
return NA;
|
||||
}
|
||||
break;
|
||||
}
|
||||
fTypeMap[key] = result;
|
||||
return result;
|
||||
}
|
||||
return *entry;
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) {
|
||||
|
@ -180,7 +180,7 @@ private:
|
||||
|
||||
void writeFieldLayout(const Layout& layout, SpvId target, int member);
|
||||
|
||||
void writeStruct(const Type& type, const MemoryLayout& layout, SpvId resultId);
|
||||
SpvId writeStruct(const Type& type, const MemoryLayout& memoryLayout);
|
||||
|
||||
void writeProgramElement(const ProgramElement& pe, OutputStream& out);
|
||||
|
||||
@ -435,6 +435,8 @@ private:
|
||||
struct Hash;
|
||||
};
|
||||
|
||||
static Instruction BuildInstructionKey(SpvOp_ opCode, const SkTArray<Word>& words);
|
||||
|
||||
// The writeOpXxxxx calls will simplify and deduplicate ops where possible.
|
||||
SpvId writeOpConstantTrue(const Type& type);
|
||||
SpvId writeOpConstantFalse(const Type& type);
|
||||
@ -492,7 +494,7 @@ private:
|
||||
SkTHashMap<IntrinsicKind, Intrinsic> fIntrinsicMap;
|
||||
SkTHashMap<const FunctionDeclaration*, SpvId> fFunctionMap;
|
||||
SkTHashMap<const Variable*, SpvId> fVariableMap;
|
||||
SkTHashMap<std::string, SpvId> fTypeMap;
|
||||
SkTHashMap<const Type*, SpvId> fStructMap;
|
||||
StringStream fGlobalInitializersBuffer;
|
||||
StringStream fConstantBuffer;
|
||||
StringStream fVariableBuffer;
|
||||
|
@ -31,10 +31,10 @@ OpDecorate %24 RelaxedPrecision
|
||||
%bool = OpTypeBool
|
||||
%_ptr_Input_bool = OpTypePointer Input %bool
|
||||
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
|
||||
%12 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%11 = OpTypeSampledImage %12
|
||||
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
|
||||
%s = OpVariable %_ptr_UniformConstant_11 UniformConstant
|
||||
%11 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%12 = OpTypeSampledImage %11
|
||||
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
||||
%s = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
||||
%mat4v4float = OpTypeMatrix %v4float 4
|
||||
%_UniformBuffer = OpTypeStruct %mat4v4float
|
||||
%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
|
||||
@ -61,7 +61,7 @@ OpDecorate %24 RelaxedPrecision
|
||||
%20 = OpLabel
|
||||
%tmpColor = OpVariable %_ptr_Function_v4float Function
|
||||
%55 = OpVariable %_ptr_Function_v4float Function
|
||||
%24 = OpLoad %11 %s
|
||||
%24 = OpLoad %12 %s
|
||||
%23 = OpImageSampleImplicitLod %v4float %24 %27
|
||||
OpStore %tmpColor %23
|
||||
%28 = OpAccessChain %_ptr_Uniform_mat4v4float %14 %int_0
|
||||
|
@ -260,10 +260,10 @@ OpDecorate %527 RelaxedPrecision
|
||||
%bool = OpTypeBool
|
||||
%_ptr_Input_bool = OpTypePointer Input %bool
|
||||
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
|
||||
%22 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%21 = OpTypeSampledImage %22
|
||||
%_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21
|
||||
%uTextureSampler_0_Stage1 = OpVariable %_ptr_UniformConstant_21 UniformConstant
|
||||
%21 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%22 = OpTypeSampledImage %21
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%uTextureSampler_0_Stage1 = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%_ptr_Input_v2float = OpTypePointer Input %v2float
|
||||
%vLocalCoord_Stage0 = OpVariable %_ptr_Input_v2float Input
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
@ -325,7 +325,7 @@ OpStore %54 %53
|
||||
OpStore %59 %58
|
||||
%62 = OpLoad %v2float %_2_subsetCoord
|
||||
OpStore %_3_clampedCoord %62
|
||||
%65 = OpLoad %21 %uTextureSampler_0_Stage1
|
||||
%65 = OpLoad %22 %uTextureSampler_0_Stage1
|
||||
%66 = OpLoad %v2float %_3_clampedCoord
|
||||
%67 = OpAccessChain %_ptr_Uniform_v4float %4 %int_6
|
||||
%68 = OpLoad %v4float %67
|
||||
|
@ -1,6 +1,6 @@
|
||||
### Compilation failed:
|
||||
|
||||
error: SPIR-V validation error: Block decoration on target <id> '4[%_arr_testBlock_int_2]' must be a structure type
|
||||
error: SPIR-V validation error: Block decoration on target <id> '8[%_arr_testBlock_int_2]' must be a structure type
|
||||
OpDecorate %_arr_testBlock_int_2 Block
|
||||
|
||||
OpCapability Shader
|
||||
|
@ -28,11 +28,11 @@ OpDecorate %26 RelaxedPrecision
|
||||
%bool = OpTypeBool
|
||||
%_ptr_Input_bool = OpTypePointer Input %bool
|
||||
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
|
||||
%12 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%11 = OpTypeSampledImage %12
|
||||
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
|
||||
%test2D = OpVariable %_ptr_UniformConstant_11 UniformConstant
|
||||
%test2DRect = OpVariable %_ptr_UniformConstant_11 UniformConstant
|
||||
%11 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%12 = OpTypeSampledImage %11
|
||||
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
||||
%test2D = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
||||
%test2DRect = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
||||
%void = OpTypeVoid
|
||||
%16 = OpTypeFunction %void
|
||||
%float_0_5 = OpConstant %float 0.5
|
||||
@ -42,13 +42,13 @@ OpDecorate %26 RelaxedPrecision
|
||||
%28 = OpConstantComposite %v3float %float_0_5 %float_0_5 %float_0_5
|
||||
%main = OpFunction %void None %16
|
||||
%17 = OpLabel
|
||||
%19 = OpLoad %11 %test2D
|
||||
%19 = OpLoad %12 %test2D
|
||||
%18 = OpImageSampleImplicitLod %v4float %19 %22
|
||||
OpStore %sk_FragColor %18
|
||||
%24 = OpLoad %11 %test2DRect
|
||||
%24 = OpLoad %12 %test2DRect
|
||||
%23 = OpImageSampleImplicitLod %v4float %24 %22
|
||||
OpStore %sk_FragColor %23
|
||||
%26 = OpLoad %11 %test2DRect
|
||||
%26 = OpLoad %12 %test2DRect
|
||||
%25 = OpImageSampleProjImplicitLod %v4float %26 %28
|
||||
OpStore %sk_FragColor %25
|
||||
OpReturn
|
||||
|
@ -1,7 +1,7 @@
|
||||
### Compilation failed:
|
||||
|
||||
error: SPIR-V validation error: Operand 3 of TypeImage requires one of these capabilities: Sampled1D Image1D
|
||||
%12 = OpTypeImage %float 1D 0 0 0 1 Unknown
|
||||
%11 = OpTypeImage %float 1D 0 0 0 1 Unknown
|
||||
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
@ -35,10 +35,10 @@ OpDecorate %35 RelaxedPrecision
|
||||
%bool = OpTypeBool
|
||||
%_ptr_Input_bool = OpTypePointer Input %bool
|
||||
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
|
||||
%12 = OpTypeImage %float 1D 0 0 0 1 Unknown
|
||||
%11 = OpTypeSampledImage %12
|
||||
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
|
||||
%tex = OpVariable %_ptr_UniformConstant_11 UniformConstant
|
||||
%11 = OpTypeImage %float 1D 0 0 0 1 Unknown
|
||||
%12 = OpTypeSampledImage %11
|
||||
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
||||
%tex = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
||||
%void = OpTypeVoid
|
||||
%15 = OpTypeFunction %void
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
@ -49,10 +49,10 @@ OpDecorate %35 RelaxedPrecision
|
||||
%16 = OpLabel
|
||||
%a = OpVariable %_ptr_Function_v4float Function
|
||||
%b = OpVariable %_ptr_Function_v4float Function
|
||||
%20 = OpLoad %11 %tex
|
||||
%20 = OpLoad %12 %tex
|
||||
%19 = OpImageSampleImplicitLod %v4float %20 %float_0
|
||||
OpStore %a %19
|
||||
%24 = OpLoad %11 %tex
|
||||
%24 = OpLoad %12 %tex
|
||||
%23 = OpImageSampleProjImplicitLod %v4float %24 %26
|
||||
OpStore %b %23
|
||||
%27 = OpLoad %v4float %a
|
||||
|
@ -30,10 +30,10 @@ OpDecorate %37 RelaxedPrecision
|
||||
%bool = OpTypeBool
|
||||
%_ptr_Input_bool = OpTypePointer Input %bool
|
||||
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
|
||||
%12 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%11 = OpTypeSampledImage %12
|
||||
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
|
||||
%tex = OpVariable %_ptr_UniformConstant_11 UniformConstant
|
||||
%11 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%12 = OpTypeSampledImage %11
|
||||
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
||||
%tex = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
||||
%void = OpTypeVoid
|
||||
%15 = OpTypeFunction %void
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
@ -46,10 +46,10 @@ OpDecorate %37 RelaxedPrecision
|
||||
%16 = OpLabel
|
||||
%a = OpVariable %_ptr_Function_v4float Function
|
||||
%b = OpVariable %_ptr_Function_v4float Function
|
||||
%20 = OpLoad %11 %tex
|
||||
%20 = OpLoad %12 %tex
|
||||
%19 = OpImageSampleImplicitLod %v4float %20 %23
|
||||
OpStore %a %19
|
||||
%26 = OpLoad %11 %tex
|
||||
%26 = OpLoad %12 %tex
|
||||
%25 = OpImageSampleProjImplicitLod %v4float %26 %28
|
||||
OpStore %b %25
|
||||
%29 = OpLoad %v4float %a
|
||||
|
@ -1,7 +1,7 @@
|
||||
### Compilation failed:
|
||||
|
||||
error: SPIR-V validation error: Operand 3 of TypeImage requires one of these capabilities: Sampled1D Image1D
|
||||
%12 = OpTypeImage %float 1D 0 0 0 1 Unknown
|
||||
%11 = OpTypeImage %float 1D 0 0 0 1 Unknown
|
||||
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
@ -39,14 +39,14 @@ OpDecorate %48 RelaxedPrecision
|
||||
%bool = OpTypeBool
|
||||
%_ptr_Input_bool = OpTypePointer Input %bool
|
||||
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
|
||||
%12 = OpTypeImage %float 1D 0 0 0 1 Unknown
|
||||
%11 = OpTypeSampledImage %12
|
||||
%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11
|
||||
%one = OpVariable %_ptr_UniformConstant_11 UniformConstant
|
||||
%16 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%15 = OpTypeSampledImage %16
|
||||
%_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
|
||||
%two = OpVariable %_ptr_UniformConstant_15 UniformConstant
|
||||
%11 = OpTypeImage %float 1D 0 0 0 1 Unknown
|
||||
%12 = OpTypeSampledImage %11
|
||||
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12
|
||||
%one = OpVariable %_ptr_UniformConstant_12 UniformConstant
|
||||
%15 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%16 = OpTypeSampledImage %15
|
||||
%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
|
||||
%two = OpVariable %_ptr_UniformConstant_16 UniformConstant
|
||||
%void = OpTypeVoid
|
||||
%19 = OpTypeFunction %void
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
@ -62,16 +62,16 @@ OpDecorate %48 RelaxedPrecision
|
||||
%b = OpVariable %_ptr_Function_v4float Function
|
||||
%c = OpVariable %_ptr_Function_v4float Function
|
||||
%d = OpVariable %_ptr_Function_v4float Function
|
||||
%24 = OpLoad %11 %one
|
||||
%24 = OpLoad %12 %one
|
||||
%23 = OpImageSampleImplicitLod %v4float %24 %float_0 Bias %float_n0_474999994
|
||||
OpStore %a %23
|
||||
%29 = OpLoad %15 %two
|
||||
%29 = OpLoad %16 %two
|
||||
%28 = OpImageSampleImplicitLod %v4float %29 %31 Bias %float_n0_474999994
|
||||
OpStore %b %28
|
||||
%34 = OpLoad %11 %one
|
||||
%34 = OpLoad %12 %one
|
||||
%33 = OpImageSampleProjImplicitLod %v4float %34 %31 Bias %float_n0_474999994
|
||||
OpStore %c %33
|
||||
%37 = OpLoad %15 %two
|
||||
%37 = OpLoad %16 %two
|
||||
%36 = OpImageSampleProjImplicitLod %v4float %37 %39 Bias %float_n0_474999994
|
||||
OpStore %d %36
|
||||
%40 = OpLoad %v4float %a
|
||||
|
Loading…
Reference in New Issue
Block a user