Implement separate sampler and textures in SkSL.
Dawn doesn't support old-style combined texturesampler uniforms, so they must be expressed as separate samplers and texture uniforms. At the SkSL Type level, I've added a Texture2D type, and expressed the Sampler2D (combined) type in terms of it. This ensures that we emit only a single OpTypeImage for it in the SPIRV. Eventually, all of the Texture types (1D, 3D, Rect) could be defined and SamplerX could simply contain a reference to TextureX. I wanted to float this idea with a single example for now (and since it's all that the Dawn backend needs). This also required adding a new "makeSampler2D" function to combine them, which maps to OpSampledImage at the SPIR-V level. Change-Id: Iaf33a6e7d339da415be6ea9a017340cb0ef3c1eb Reviewed-on: https://skia-review.googlesource.com/c/skia/+/229417 Commit-Queue: Stephen White <senorblanco@chromium.org> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
6f6d2de95c
commit
ff5d7a2f90
@ -371,8 +371,10 @@ enum GrSLType {
|
||||
kTexture2DSampler_GrSLType,
|
||||
kTextureExternalSampler_GrSLType,
|
||||
kTexture2DRectSampler_GrSLType,
|
||||
kTexture2D_GrSLType,
|
||||
kSampler_GrSLType,
|
||||
|
||||
kLast_GrSLType = kTexture2DRectSampler_GrSLType
|
||||
kLast_GrSLType = kSampler_GrSLType
|
||||
};
|
||||
static const int kGrSLTypeCount = kLast_GrSLType + 1;
|
||||
|
||||
@ -474,6 +476,8 @@ static constexpr bool GrSLTypeIsFloatType(GrSLType type) {
|
||||
case kInt4_GrSLType:
|
||||
case kUint_GrSLType:
|
||||
case kUint2_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
return false;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
@ -531,6 +535,8 @@ static constexpr int GrSLTypeVecLength(GrSLType type) {
|
||||
case kTexture2DSampler_GrSLType:
|
||||
case kTextureExternalSampler_GrSLType:
|
||||
case kTexture2DRectSampler_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
return -1;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
@ -612,6 +618,8 @@ static constexpr bool GrSLTypeIsCombinedSamplerType(GrSLType type) {
|
||||
case kUShort2_GrSLType:
|
||||
case kUShort3_GrSLType:
|
||||
case kUShort4_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
return false;
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
|
@ -92,6 +92,10 @@ const char* GrGLSLTypeString(GrSLType t) {
|
||||
return "ubyte3";
|
||||
case kUByte4_GrSLType:
|
||||
return "ubyte4";
|
||||
case kTexture2D_GrSLType:
|
||||
return "texture2D";
|
||||
case kSampler_GrSLType:
|
||||
return "sampler";
|
||||
}
|
||||
SK_ABORT("Unknown shader var type.");
|
||||
return ""; // suppress warning
|
||||
|
@ -85,6 +85,8 @@ static uint32_t grsltype_to_alignment_mask(GrSLType type) {
|
||||
case kTexture2DSampler_GrSLType:
|
||||
case kTextureExternalSampler_GrSLType:
|
||||
case kTexture2DRectSampler_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
break;
|
||||
}
|
||||
SK_ABORT("Unexpected type");
|
||||
@ -166,6 +168,8 @@ static inline uint32_t grsltype_to_mtl_size(GrSLType type) {
|
||||
case kTexture2DSampler_GrSLType:
|
||||
case kTextureExternalSampler_GrSLType:
|
||||
case kTexture2DRectSampler_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
break;
|
||||
}
|
||||
SK_ABORT("Unexpected type");
|
||||
|
@ -84,6 +84,8 @@ static uint32_t grsltype_to_alignment_mask(GrSLType type) {
|
||||
case kTexture2DSampler_GrSLType:
|
||||
case kTextureExternalSampler_GrSLType:
|
||||
case kTexture2DRectSampler_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
break;
|
||||
}
|
||||
SK_ABORT("Unexpected type");
|
||||
@ -166,6 +168,8 @@ static inline uint32_t grsltype_to_vk_size(GrSLType type) {
|
||||
case kTexture2DSampler_GrSLType:
|
||||
case kTextureExternalSampler_GrSLType:
|
||||
case kTexture2DRectSampler_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
break;
|
||||
}
|
||||
SK_ABORT("Unexpected type");
|
||||
|
@ -55,6 +55,8 @@ static inline int grsltype_to_location_size(GrSLType type) {
|
||||
case kHalf4x4_GrSLType:
|
||||
return 4;
|
||||
case kTexture2DSampler_GrSLType:
|
||||
case kSampler_GrSLType:
|
||||
case kTexture2D_GrSLType:
|
||||
return 0;
|
||||
case kTextureExternalSampler_GrSLType:
|
||||
return 0;
|
||||
|
@ -211,6 +211,8 @@ Compiler::Compiler(Flags flags)
|
||||
ADD_TYPE(GSamplerCubeArrayShadow);
|
||||
ADD_TYPE(FragmentProcessor);
|
||||
ADD_TYPE(SkRasterPipeline);
|
||||
ADD_TYPE(Sampler);
|
||||
ADD_TYPE(Texture2D);
|
||||
|
||||
StringFragment skCapsName("sk_Caps");
|
||||
Variable* skCaps = new Variable(-1, Modifiers(), skCapsName,
|
||||
|
@ -91,8 +91,9 @@ public:
|
||||
, fDouble4x2_Type(new Type("double4x2", *fDouble_Type, 4, 2))
|
||||
, fDouble4x3_Type(new Type("double4x3", *fDouble_Type, 4, 3))
|
||||
, fDouble4x4_Type(new Type("double4x4", *fDouble_Type, 4, 4))
|
||||
, fTexture2D_Type(new Type("texture2D", Type::kTexture_Kind))
|
||||
, fSampler1D_Type(new Type("sampler1D", SpvDim1D, false, false, false, true))
|
||||
, fSampler2D_Type(new Type("sampler2D", SpvDim2D, false, false, false, true))
|
||||
, fSampler2D_Type(new Type("sampler2D", SpvDim2D, false, false, false, true, &*fTexture2D_Type))
|
||||
, fSampler3D_Type(new Type("sampler3D", SpvDim3D, false, false, false, true))
|
||||
, fSamplerExternalOES_Type(new Type("samplerExternalOES", SpvDim2D, false, false,
|
||||
false, true))
|
||||
@ -116,6 +117,7 @@ public:
|
||||
// Related to below FIXME, gsampler*s don't currently expand to cover integer case.
|
||||
, fISampler2D_Type(new Type("isampler2D", SpvDim2D, false, false, false, true))
|
||||
|
||||
, fSampler_Type(new Type("sampler", Type::kSeparateSampler_Kind))
|
||||
// FIXME express these as "gimage2D" that expand to image2D, iimage2D, and uimage2D.
|
||||
, fImage2D_Type(new Type("image2D", SpvDim2D, false, false, false, true))
|
||||
, fIImage2D_Type(new Type("iimage2D", SpvDim2D, false, false, false, true))
|
||||
@ -293,6 +295,8 @@ public:
|
||||
const std::unique_ptr<Type> fDouble4x3_Type;
|
||||
const std::unique_ptr<Type> fDouble4x4_Type;
|
||||
|
||||
const std::unique_ptr<Type> fTexture2D_Type;
|
||||
|
||||
const std::unique_ptr<Type> fSampler1D_Type;
|
||||
const std::unique_ptr<Type> fSampler2D_Type;
|
||||
const std::unique_ptr<Type> fSampler3D_Type;
|
||||
@ -314,6 +318,7 @@ public:
|
||||
const std::unique_ptr<Type> fSamplerCubeArrayShadow_Type;
|
||||
|
||||
const std::unique_ptr<Type> fISampler2D_Type;
|
||||
const std::unique_ptr<Type> fSampler_Type;
|
||||
|
||||
const std::unique_ptr<Type> fImage2D_Type;
|
||||
const std::unique_ptr<Type> fIImage2D_Type;
|
||||
|
@ -101,6 +101,8 @@ void SPIRVCodeGenerator::setupIntrinsics() {
|
||||
fIntrinsicMap[String("dFdy")] = SPECIAL(DFdy);
|
||||
fIntrinsicMap[String("fwidth")] = std::make_tuple(kSPIRV_IntrinsicKind, SpvOpFwidth,
|
||||
SpvOpUndef, SpvOpUndef, SpvOpUndef);
|
||||
fIntrinsicMap[String("makeSampler2D")] = SPECIAL(SampledImage);
|
||||
|
||||
fIntrinsicMap[String("texture")] = SPECIAL(Texture);
|
||||
fIntrinsicMap[String("subpassLoad")] = SPECIAL(SubpassLoad);
|
||||
|
||||
@ -206,6 +208,7 @@ void SPIRVCodeGenerator::writeOpCode(SpvOp_ opCode, int length, OutputStream& ou
|
||||
case SpvOpTypeStruct: // fall through
|
||||
case SpvOpTypeImage: // fall through
|
||||
case SpvOpTypeSampledImage: // fall through
|
||||
case SpvOpTypeSampler: // fall through
|
||||
case SpvOpVariable: // fall through
|
||||
case SpvOpFunction: // fall through
|
||||
case SpvOpFunctionParameter: // fall through
|
||||
@ -526,22 +529,42 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
|
||||
case Type::kSampler_Kind: {
|
||||
SpvId image = result;
|
||||
if (SpvDimSubpassData != type.dimensions()) {
|
||||
image = this->nextId();
|
||||
if (type.textureType()) {
|
||||
image = this->getType(*type.textureType(), layout);
|
||||
} else {
|
||||
image = nextId();
|
||||
}
|
||||
}
|
||||
if (SpvDimBuffer == type.dimensions()) {
|
||||
fCapabilities |= (((uint64_t) 1) << SpvCapabilitySampledBuffer);
|
||||
}
|
||||
this->writeInstruction(SpvOpTypeImage, image,
|
||||
this->getType(*fContext.fFloat_Type, layout),
|
||||
type.dimensions(), type.isDepth(), type.isArrayed(),
|
||||
type.isMultisampled(), type.isSampled() ? 1 : 2,
|
||||
SpvImageFormatUnknown, fConstantBuffer);
|
||||
fImageTypeMap[key] = image;
|
||||
if (!type.textureType()) {
|
||||
this->writeInstruction(SpvOpTypeImage, image,
|
||||
this->getType(*fContext.fFloat_Type, layout),
|
||||
type.dimensions(), type.isDepth(), type.isArrayed(),
|
||||
type.isMultisampled(), type.isSampled() ? 1 : 2,
|
||||
SpvImageFormatUnknown, fConstantBuffer);
|
||||
fImageTypeMap[key] = image;
|
||||
}
|
||||
if (SpvDimSubpassData != type.dimensions()) {
|
||||
this->writeInstruction(SpvOpTypeSampledImage, result, image, fConstantBuffer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Type::kSeparateSampler_Kind: {
|
||||
this->writeInstruction(SpvOpTypeSampler, result, fConstantBuffer);
|
||||
break;
|
||||
}
|
||||
case Type::kTexture_Kind: {
|
||||
// FIXME: should support more than 2D
|
||||
this->writeInstruction(SpvOpTypeImage, result,
|
||||
this->getType(*fContext.fFloat_Type, layout),
|
||||
SpvDim2D, type.isDepth(), type.isArrayed(),
|
||||
type.isMultisampled(), 1,
|
||||
SpvImageFormatUnknown, fConstantBuffer);
|
||||
fImageTypeMap[key] = result;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (type == *fContext.fVoid_Type) {
|
||||
this->writeInstruction(SpvOpTypeVoid, result, fConstantBuffer);
|
||||
@ -819,6 +842,18 @@ SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIn
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSampledImage_SpecialIntrinsic: {
|
||||
SkASSERT(2 == c.fArguments.size());
|
||||
SpvId img = this->writeExpression(*c.fArguments[0], out);
|
||||
SpvId sampler = this->writeExpression(*c.fArguments[1], out);
|
||||
this->writeInstruction(SpvOpSampledImage,
|
||||
this->getType(c.fType),
|
||||
result,
|
||||
img,
|
||||
sampler,
|
||||
out);
|
||||
break;
|
||||
}
|
||||
case kSubpassLoad_SpecialIntrinsic: {
|
||||
SpvId img = this->writeExpression(*c.fArguments[0], out);
|
||||
std::vector<std::unique_ptr<Expression>> args;
|
||||
@ -2708,7 +2743,9 @@ void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclaratio
|
||||
} else if (var->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
storageClass = SpvStorageClassOutput;
|
||||
} else if (var->fModifiers.fFlags & Modifiers::kUniform_Flag) {
|
||||
if (var->fType.kind() == Type::kSampler_Kind) {
|
||||
if (var->fType.kind() == Type::kSampler_Kind ||
|
||||
var->fType.kind() == Type::kSeparateSampler_Kind ||
|
||||
var->fType.kind() == Type::kTexture_Kind) {
|
||||
storageClass = SpvStorageClassUniformConstant;
|
||||
} else {
|
||||
storageClass = SpvStorageClassUniform;
|
||||
|
@ -134,6 +134,7 @@ private:
|
||||
kMod_SpecialIntrinsic,
|
||||
kDFdy_SpecialIntrinsic,
|
||||
kSaturate_SpecialIntrinsic,
|
||||
kSampledImage_SpecialIntrinsic,
|
||||
kSubpassLoad_SpecialIntrinsic,
|
||||
kTexture_SpecialIntrinsic,
|
||||
};
|
||||
|
@ -49,8 +49,10 @@ public:
|
||||
kMatrix_Kind,
|
||||
kOther_Kind,
|
||||
kSampler_Kind,
|
||||
kSeparateSampler_Kind,
|
||||
kScalar_Kind,
|
||||
kStruct_Kind,
|
||||
kTexture_Kind,
|
||||
kVector_Kind
|
||||
};
|
||||
|
||||
@ -194,7 +196,7 @@ public:
|
||||
|
||||
// Create a sampler type.
|
||||
Type(const char* name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled,
|
||||
bool isSampled)
|
||||
bool isSampled, Type* textureType = nullptr)
|
||||
: INHERITED(-1, kType_Kind, StringFragment())
|
||||
, fNameString(name)
|
||||
, fTypeKind(kSampler_Kind)
|
||||
@ -203,7 +205,9 @@ public:
|
||||
, fIsDepth(isDepth)
|
||||
, fIsArrayed(isArrayed)
|
||||
, fIsMultisampled(isMultisampled)
|
||||
, fIsSampled(isSampled) {
|
||||
, fIsSampled(isSampled)
|
||||
, fTextureType(textureType)
|
||||
{
|
||||
fName.fChars = fNameString.c_str();
|
||||
fName.fLength = fNameString.size();
|
||||
}
|
||||
@ -304,6 +308,14 @@ public:
|
||||
return *fComponentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* For texturesamplers, returns the type of texture it samples (e.g., sampler2D has
|
||||
* a texture type of texture2D).
|
||||
*/
|
||||
const Type* textureType() const {
|
||||
return fTextureType;
|
||||
}
|
||||
|
||||
/**
|
||||
* For nullable types, returns the base type, otherwise returns the type itself.
|
||||
*/
|
||||
@ -349,27 +361,27 @@ public:
|
||||
}
|
||||
|
||||
SpvDim_ dimensions() const {
|
||||
SkASSERT(kSampler_Kind == fTypeKind);
|
||||
SkASSERT(kSampler_Kind == fTypeKind || kTexture_Kind == fTypeKind);
|
||||
return fDimensions;
|
||||
}
|
||||
|
||||
bool isDepth() const {
|
||||
SkASSERT(kSampler_Kind == fTypeKind);
|
||||
SkASSERT(kSampler_Kind == fTypeKind || kTexture_Kind == fTypeKind);
|
||||
return fIsDepth;
|
||||
}
|
||||
|
||||
bool isArrayed() const {
|
||||
SkASSERT(kSampler_Kind == fTypeKind);
|
||||
SkASSERT(kSampler_Kind == fTypeKind || kTexture_Kind == fTypeKind);
|
||||
return fIsArrayed;
|
||||
}
|
||||
|
||||
bool isMultisampled() const {
|
||||
SkASSERT(kSampler_Kind == fTypeKind);
|
||||
SkASSERT(kSampler_Kind == fTypeKind || kTexture_Kind == fTypeKind);
|
||||
return fIsMultisampled;
|
||||
}
|
||||
|
||||
bool isSampled() const {
|
||||
SkASSERT(kSampler_Kind == fTypeKind);
|
||||
SkASSERT(kSampler_Kind == fTypeKind || kTexture_Kind == fTypeKind);
|
||||
return fIsSampled;
|
||||
}
|
||||
|
||||
@ -405,6 +417,7 @@ private:
|
||||
bool fIsMultisampled = false;
|
||||
bool fIsSampled = false;
|
||||
bool fHighPrecision = false;
|
||||
const Type* fTextureType = nullptr;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -254,6 +254,7 @@ $genIType findLSB($genUType value);
|
||||
$genIType findMSB($genIType value);
|
||||
$genIType findMSB($genUType value);
|
||||
|
||||
sampler2D makeSampler2D(texture2D texture, sampler sampler);
|
||||
int2 textureSize($gsampler2DRect sampler);
|
||||
|
||||
half4 texture($gsampler1D sampler, float P);
|
||||
|
Loading…
Reference in New Issue
Block a user