SkSL: implement full support for separate textures and samplers.

This extends the support for separate textures and samplers to include 1D, 2D,
3D, ExternalOES, Cube, 2DRect, Buffer and ISampler2D. The new texture types are
now mandatory for a texturesampler which generates SPIR-V, so we can remove the
special case code for 2D previously landed.

Change-Id: Iec4bd6dc456169e6f4914ac416a10cd9720c42e0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/230556
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h
index b566a5e..e06bac1 100644
--- a/src/sksl/SkSLContext.h
+++ b/src/sksl/SkSLContext.h
@@ -91,19 +91,24 @@
     , 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, &*fTexture2D_Type))
-    , fSampler3D_Type(new Type("sampler3D", SpvDim3D, false, false, false, true))
-    , fSamplerExternalOES_Type(new Type("samplerExternalOES", SpvDim2D, false, false,
-                                        false, true))
-    , fSamplerCube_Type(new Type("samplerCube", SpvDimCube, false, false, false, true))
-    , fSampler2DRect_Type(new Type("sampler2DRect", SpvDimRect, false, false, false, true))
+    , fTexture1D_Type(new Type("texture1D", SpvDim1D, false, false, false, true))
+    , fTexture2D_Type(new Type("texture2D", SpvDim2D, false, false, false, true))
+    , fTexture3D_Type(new Type("texture3D", SpvDim3D, false, false, false, true))
+    , fTextureExternalOES_Type(new Type("textureExternalOES", SpvDim2D, false, false, false, true))
+    , fTextureCube_Type(new Type("textureCube", SpvDimCube, false, false, false, true))
+    , fTexture2DRect_Type(new Type("texture2DRect", SpvDimRect, false, false, false, true))
+    , fTextureBuffer_Type(new Type("textureBuffer", SpvDimBuffer, false, false, false, true))
+    , fITexture2D_Type(new Type("itexture2D", SpvDim2D, false, false, false, true))
+    , fSampler1D_Type(new Type("sampler1D", *fTexture1D_Type))
+    , fSampler2D_Type(new Type("sampler2D", *fTexture2D_Type))
+    , fSampler3D_Type(new Type("sampler3D", *fTexture3D_Type))
+    , fSamplerExternalOES_Type(new Type("samplerExternalOES", *fTextureExternalOES_Type))
+    , fSamplerCube_Type(new Type("samplerCube", *fTextureCube_Type))
+    , fSampler2DRect_Type(new Type("sampler2DRect", *fTexture2DRect_Type))
     , fSampler1DArray_Type(new Type("sampler1DArray"))
     , fSampler2DArray_Type(new Type("sampler2DArray"))
     , fSamplerCubeArray_Type(new Type("samplerCubeArray"))
-    , fSamplerBuffer_Type(new Type("samplerBuffer", SpvDimBuffer, false, false, false,
-                                   true))
+    , fSamplerBuffer_Type(new Type("samplerBuffer", *fTextureBuffer_Type))
     , fSampler2DMS_Type(new Type("sampler2DMS"))
     , fSampler2DMSArray_Type(new Type("sampler2DMSArray"))
     , fSampler1DShadow_Type(new Type("sampler1DShadow"))
@@ -115,7 +120,7 @@
     , fSamplerCubeArrayShadow_Type(new Type("samplerCubeArrayShadow"))
 
     // Related to below FIXME, gsampler*s don't currently expand to cover integer case.
-    , fISampler2D_Type(new Type("isampler2D", SpvDim2D, false, false, false, true))
+    , fISampler2D_Type(new Type("isampler2D", *fITexture2D_Type))
 
     , fSampler_Type(new Type("sampler", Type::kSeparateSampler_Kind))
     // FIXME express these as "gimage2D" that expand to image2D, iimage2D, and uimage2D.
@@ -295,7 +300,14 @@
     const std::unique_ptr<Type> fDouble4x3_Type;
     const std::unique_ptr<Type> fDouble4x4_Type;
 
+    const std::unique_ptr<Type> fTexture1D_Type;
     const std::unique_ptr<Type> fTexture2D_Type;
+    const std::unique_ptr<Type> fTexture3D_Type;
+    const std::unique_ptr<Type> fTextureExternalOES_Type;
+    const std::unique_ptr<Type> fTextureCube_Type;
+    const std::unique_ptr<Type> fTexture2DRect_Type;
+    const std::unique_ptr<Type> fTextureBuffer_Type;
+    const std::unique_ptr<Type> fITexture2D_Type;
 
     const std::unique_ptr<Type> fSampler1D_Type;
     const std::unique_ptr<Type> fSampler2D_Type;
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index 2833d7c..e2071c7 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -529,23 +529,11 @@
             case Type::kSampler_Kind: {
                 SpvId image = result;
                 if (SpvDimSubpassData != type.dimensions()) {
-                    if (type.textureType()) {
-                        image = this->getType(*type.textureType(), layout);
-                    } else {
-                        image = nextId();
-                    }
+                    image = this->getType(type.textureType(), layout);
                 }
                 if (SpvDimBuffer == type.dimensions()) {
                     fCapabilities |= (((uint64_t) 1) << SpvCapabilitySampledBuffer);
                 }
-                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);
                 }
@@ -556,11 +544,10 @@
                 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,
+                                       type.dimensions(), type.isDepth(), type.isArrayed(),
+                                       type.isMultisampled(), type.isSampled() ? 1 : 2,
                                        SpvImageFormatUnknown, fConstantBuffer);
                 fImageTypeMap[key] = result;
                 break;
diff --git a/src/sksl/ir/SkSLType.h b/src/sksl/ir/SkSLType.h
index 6b474b1..49ea8a5 100644
--- a/src/sksl/ir/SkSLType.h
+++ b/src/sksl/ir/SkSLType.h
@@ -194,19 +194,35 @@
         fName.fLength = fNameString.size();
     }
 
-    // Create a sampler type.
+    // Create a texture type.
     Type(const char* name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled,
-         bool isSampled, Type* textureType = nullptr)
+         bool isSampled)
     : INHERITED(-1, kType_Kind, StringFragment())
     , fNameString(name)
-    , fTypeKind(kSampler_Kind)
+    , fTypeKind(kTexture_Kind)
     , fNumberKind(kNonnumeric_NumberKind)
     , fDimensions(dimensions)
     , fIsDepth(isDepth)
     , fIsArrayed(isArrayed)
     , fIsMultisampled(isMultisampled)
     , fIsSampled(isSampled)
-    , fTextureType(textureType)
+    {
+        fName.fChars = fNameString.c_str();
+        fName.fLength = fNameString.size();
+    }
+
+    // Create a sampler type.
+    Type(const char* name, const Type& textureType)
+    : INHERITED(-1, kType_Kind, StringFragment())
+    , fNameString(name)
+    , fTypeKind(kSampler_Kind)
+    , fNumberKind(kNonnumeric_NumberKind)
+    , fDimensions(textureType.dimensions())
+    , fIsDepth(textureType.isDepth())
+    , fIsArrayed(textureType.isArrayed())
+    , fIsMultisampled(textureType.isMultisampled())
+    , fIsSampled(textureType.isSampled())
+    , fTextureType(&textureType)
     {
         fName.fChars = fNameString.c_str();
         fName.fLength = fNameString.size();
@@ -312,8 +328,9 @@
      * For texturesamplers, returns the type of texture it samples (e.g., sampler2D has
      * a texture type of texture2D).
      */
-    const Type* textureType() const {
-        return fTextureType;
+    const Type& textureType() const {
+        SkASSERT(fTextureType);
+        return *fTextureType;
     }
 
     /**