Vulkan: Implement simple render-to-texture.

This was mostly working already, just needed to set up a few entry
points.

BUG=angleproject:2200

Change-Id: I9c13d6d4dd42f23c69a58e42e07e3e28877671a1
Reviewed-on: https://chromium-review.googlesource.com/734237
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 9c8d155..2931e63 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -359,8 +359,7 @@
 
 bool FramebufferVk::checkStatus(const gl::Context *context) const
 {
-    UNIMPLEMENTED();
-    return bool();
+    return true;
 }
 
 void FramebufferVk::syncState(const gl::Context *context,
@@ -618,7 +617,6 @@
     // Updated the cached image layout of the attachments in this FBO.
     // For a default FBO, we need to call through to the WindowSurfaceVk
     // TODO(jmadill): Iterate over all attachments.
-    ASSERT(mBackbuffer);
     RenderTargetVk *renderTarget = nullptr;
     ANGLE_TRY(mState.getFirstColorAttachment()->getRenderTarget(context, &renderTarget));
     renderTarget->image->updateLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index 9580e35..749733b 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -533,6 +533,7 @@
     outCaps->maxElementIndex              = std::numeric_limits<GLuint>::max() - 1;
     outCaps->maxFragmentUniformVectors    = 8;
     outCaps->maxVertexUniformVectors      = 8;
+    outCaps->maxColorAttachments          = 1;
 
     // Enable this for simple buffer readback testing, but some functionality is missing.
     // TODO(jmadill): Support full mapBufferRange extension.
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index 58c0626..28d9f64 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -150,6 +150,13 @@
 
     ANGLE_TRY(mSampler.init(device, samplerInfo));
 
+    mRenderTarget.image     = &mImage;
+    mRenderTarget.imageView = &mImageView;
+    mRenderTarget.format    = &vkFormat;
+    mRenderTarget.extents   = size;
+    mRenderTarget.samples   = VK_SAMPLE_COUNT_1_BIT;
+    mRenderTarget.resource  = this;
+
     // Handle initial data.
     // TODO(jmadill): Consider re-using staging texture.
     if (pixels)
@@ -336,8 +343,10 @@
                                                const gl::ImageIndex &imageIndex,
                                                FramebufferAttachmentRenderTarget **rtOut)
 {
-    UNIMPLEMENTED();
-    return gl::InternalError();
+    ASSERT(imageIndex.type == GL_TEXTURE_2D);
+    ASSERT(imageIndex.mipIndex == 0 && imageIndex.layerIndex == gl::ImageIndex::ENTIRE_LEVEL);
+    *rtOut = &mRenderTarget;
+    return gl::NoError();
 }
 
 void TextureVk::syncState(const gl::Texture::DirtyBits &dirtyBits)
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.h b/src/libANGLE/renderer/vulkan/TextureVk.h
index f2b6910..10be485 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.h
+++ b/src/libANGLE/renderer/vulkan/TextureVk.h
@@ -11,6 +11,7 @@
 #define LIBANGLE_RENDERER_VULKAN_TEXTUREVK_H_
 
 #include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
 #include "libANGLE/renderer/vulkan/renderervk_utils.h"
 
 namespace rx
@@ -120,6 +121,8 @@
     vk::DeviceMemory mDeviceMemory;
     vk::ImageView mImageView;
     vk::Sampler mSampler;
+
+    RenderTargetVk mRenderTarget;
 };
 
 }  // namespace rx
diff --git a/src/tests/gl_tests/SimpleOperationTest.cpp b/src/tests/gl_tests/SimpleOperationTest.cpp
index 8f0d4e8..7701ac4 100644
--- a/src/tests/gl_tests/SimpleOperationTest.cpp
+++ b/src/tests/gl_tests/SimpleOperationTest.cpp
@@ -494,6 +494,41 @@
     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
 }
 
+// Tests rendering to a user framebuffer.
+TEST_P(SimpleOperationTest, RenderToTexture)
+{
+    constexpr int kSize = 16;
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    glViewport(0, 0, kSize, kSize);
+
+    const std::string &vertexShader =
+        "attribute vec3 position;\n"
+        "void main()\n"
+        "{\n"
+        "    gl_Position = vec4(position, 1);\n"
+        "}";
+    const std::string &fragmentShader =
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = vec4(0, 1, 0, 1);\n"
+        "}";
+    ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
+    drawQuad(program, "position", 0.5f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
 ANGLE_INSTANTIATE_TEST(SimpleOperationTest,
                        ES2_D3D9(),