Vulkan: Add vk::GetImpl helper.

Using reflection helpers, we can avoid having to pass the return
type to the GetImpl method.

BUG=angleproject:2200

Change-Id: Id160fbdf0ea8b3de2f219d3cc92394c678189a48
Reviewed-on: https://chromium-review.googlesource.com/742371
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
index d7d2503..e93309f 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -257,10 +257,10 @@
     const auto &state     = mState.getState();
     const auto &programGL = state.getProgram();
     const auto &vao       = state.getVertexArray();
-    const auto &programVk = GetImplAs<ProgramVk>(programGL);
     const auto *drawFBO   = state.getDrawFramebuffer();
-    FramebufferVk *vkFBO  = GetImplAs<FramebufferVk>(drawFBO);
-    VertexArrayVk *vkVAO  = GetImplAs<VertexArrayVk>(vao);
+    ProgramVk *programVk  = vk::GetImpl(programGL);
+    FramebufferVk *vkFBO  = vk::GetImpl(drawFBO);
+    VertexArrayVk *vkVAO  = vk::GetImpl(vao);
 
     // Ensure the attribs and bindings are updated.
     vkVAO->updateVertexDescriptions(context);
@@ -309,11 +309,11 @@
 
     const auto &state     = mState.getState();
     const auto &programGL = state.getProgram();
-    ProgramVk *programVk  = GetImplAs<ProgramVk>(programGL);
+    ProgramVk *programVk  = vk::GetImpl(programGL);
     const auto &vao       = state.getVertexArray();
-    VertexArrayVk *vkVAO  = GetImplAs<VertexArrayVk>(vao);
+    VertexArrayVk *vkVAO  = vk::GetImpl(vao);
     const auto *drawFBO   = state.getDrawFramebuffer();
-    FramebufferVk *vkFBO  = GetImplAs<FramebufferVk>(drawFBO);
+    FramebufferVk *vkFBO  = vk::GetImpl(drawFBO);
     Serial queueSerial    = mRenderer->getCurrentQueueSerial();
     uint32_t maxAttrib    = programGL->getState().getMaxActiveAttribLocation();
 
@@ -336,7 +336,7 @@
     vkVAO->updateCurrentBufferSerials(programGL->getActiveAttribLocationsMask(), queueSerial);
 
     // TODO(jmadill): Can probably use more dirty bits here.
-    ContextVk *contextVk = GetImplAs<ContextVk>(context);
+    ContextVk *contextVk = vk::GetImpl(context);
     ANGLE_TRY(programVk->updateUniforms(contextVk));
     programVk->updateTexturesDescriptorSet(contextVk);
 
@@ -406,7 +406,7 @@
         mState.getState().getVertexArray()->getElementArrayBuffer().get();
     ASSERT(elementArrayBuffer);
 
-    BufferVk *elementArrayBufferVk = GetImplAs<BufferVk>(elementArrayBuffer);
+    BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
 
     commandBuffer->bindIndexBuffer(elementArrayBufferVk->getVkBuffer(), 0, GetVkIndexType(type));
     commandBuffer->drawIndexed(count, 1, 0, 0, 0);
@@ -707,12 +707,12 @@
             case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
             {
                 // { vertex, fragment }
-                ProgramVk *programVk           = GetImplAs<ProgramVk>(glState.getProgram());
+                ProgramVk *programVk           = vk::GetImpl(glState.getProgram());
                 mCurrentShaderStages[0].module = programVk->getLinkedVertexModule().getHandle();
                 mCurrentShaderStages[1].module = programVk->getLinkedFragmentModule().getHandle();
 
                 // Also invalidate the vertex descriptions cache in the Vertex Array.
-                VertexArrayVk *vaoVk = GetImplAs<VertexArrayVk>(glState.getVertexArray());
+                VertexArrayVk *vaoVk = vk::GetImpl(glState.getVertexArray());
                 vaoVk->invalidateVertexDescriptions();
 
                 dirtyTextures = true;
@@ -761,7 +761,7 @@
 
     if (dirtyTextures)
     {
-        ProgramVk *programVk = GetImplAs<ProgramVk>(glState.getProgram());
+        ProgramVk *programVk = vk::GetImpl(glState.getProgram());
         programVk->invalidateTextures();
     }
 }
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index b38ab13..1e697b5 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -96,7 +96,7 @@
 
 void FramebufferVk::destroy(const gl::Context *context)
 {
-    RendererVk *renderer = GetImplAs<ContextVk>(context)->getRenderer();
+    RendererVk *renderer = vk::GetImpl(context)->getRenderer();
 
     renderer->releaseResource(*this, &mRenderPass);
     renderer->releaseResource(*this, &mFramebuffer);
@@ -104,7 +104,7 @@
 
 void FramebufferVk::destroyDefault(const egl::Display *display)
 {
-    VkDevice device = GetImplAs<DisplayVk>(display)->getRenderer()->getDevice();
+    VkDevice device = vk::GetImpl(display)->getRenderer()->getDevice();
 
     mRenderPass.destroy(device);
     mFramebuffer.destroy(device);
@@ -137,7 +137,7 @@
 
 gl::Error FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
 {
-    ContextVk *contextVk = GetImplAs<ContextVk>(context);
+    ContextVk *contextVk = vk::GetImpl(context);
 
     if (mState.getDepthAttachment() && (mask & GL_DEPTH_BUFFER_BIT) != 0)
     {
@@ -266,7 +266,7 @@
     RenderTargetVk *renderTarget = nullptr;
     ANGLE_TRY(readAttachment->getRenderTarget(context, &renderTarget));
 
-    ContextVk *contextVk = GetImplAs<ContextVk>(context);
+    ContextVk *contextVk = vk::GetImpl(context);
     RendererVk *renderer = contextVk->getRenderer();
     VkDevice device      = renderer->getDevice();
 
@@ -355,7 +355,7 @@
 void FramebufferVk::syncState(const gl::Context *context,
                               const gl::Framebuffer::DirtyBits &dirtyBits)
 {
-    ContextVk *contextVk = GetImplAs<ContextVk>(context);
+    ContextVk *contextVk = vk::GetImpl(context);
     RendererVk *renderer = contextVk->getRenderer();
 
     ASSERT(dirtyBits.any());
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
index d942cd6..7902353 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -62,7 +62,7 @@
 
     ANGLE_TRY(storageOut->buffer.init(device, uniformBufferInfo));
 
-    ANGLE_TRY(AllocateBufferMemory(GetImplAs<ContextVk>(context), blockSize, &storageOut->buffer,
+    ANGLE_TRY(AllocateBufferMemory(vk::GetImpl(context), blockSize, &storageOut->buffer,
                                    &storageOut->memory, requiredSizeOut));
 
     return gl::NoError();
@@ -145,7 +145,7 @@
 
 void ProgramVk::destroy(const gl::Context *contextImpl)
 {
-    VkDevice device = GetImplAs<ContextVk>(contextImpl)->getDevice();
+    VkDevice device = vk::GetImpl(contextImpl)->getDevice();
     reset(device);
 }
 
@@ -202,7 +202,7 @@
                                const gl::VaryingPacking &packing,
                                gl::InfoLog &infoLog)
 {
-    ContextVk *contextVk           = GetImplAs<ContextVk>(glContext);
+    ContextVk *contextVk           = vk::GetImpl(glContext);
     RendererVk *renderer           = contextVk->getRenderer();
     GlslangWrapper *glslangWrapper = renderer->getGlslangWrapper();
     VkDevice device                = renderer->getDevice();
@@ -250,7 +250,7 @@
 
 gl::Error ProgramVk::initDefaultUniformBlocks(const gl::Context *glContext)
 {
-    ContextVk *contextVk = GetImplAs<ContextVk>(glContext);
+    ContextVk *contextVk = vk::GetImpl(glContext);
     VkDevice device      = contextVk->getDevice();
 
     // Process vertex and fragment uniforms into std140 packing.
@@ -836,7 +836,7 @@
         // TODO(jmadill): Incomplete textures handling.
         ASSERT(texture);
 
-        TextureVk *textureVk   = GetImplAs<TextureVk>(texture);
+        TextureVk *textureVk   = vk::GetImpl(texture);
         const vk::Image &image = textureVk->getImage();
 
         VkDescriptorImageInfo &imageInfo = descriptorImageInfo[imageCount];
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
index 685a70c..5ac4b4f 100644
--- a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -183,7 +183,7 @@
 
 void WindowSurfaceVk::destroy(const egl::Display *display)
 {
-    const DisplayVk *displayVk = GetImplAs<DisplayVk>(display);
+    const DisplayVk *displayVk = vk::GetImpl(display);
     RendererVk *rendererVk     = displayVk->getRenderer();
     VkDevice device            = rendererVk->getDevice();
     VkInstance instance        = rendererVk->getInstance();
@@ -218,7 +218,7 @@
 
 egl::Error WindowSurfaceVk::initialize(const egl::Display *display)
 {
-    const DisplayVk *displayVk = GetImplAs<DisplayVk>(display);
+    const DisplayVk *displayVk = vk::GetImpl(display);
     return initializeImpl(displayVk->getRenderer()).toEGL(EGL_BAD_SURFACE);
 }
 
@@ -419,7 +419,7 @@
 
 egl::Error WindowSurfaceVk::swap(const gl::Context *context)
 {
-    const DisplayVk *displayVk = GetImplAs<DisplayVk>(context->getCurrentDisplay());
+    const DisplayVk *displayVk = vk::GetImpl(context->getCurrentDisplay());
     RendererVk *renderer       = displayVk->getRenderer();
 
     vk::CommandBuffer *currentCB = nullptr;
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index 0b15df5..9553972 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -28,7 +28,7 @@
 
 gl::Error TextureVk::onDestroy(const gl::Context *context)
 {
-    ContextVk *contextVk = GetImplAs<ContextVk>(context);
+    ContextVk *contextVk = vk::GetImpl(context);
     RendererVk *renderer = contextVk->getRenderer();
 
     renderer->releaseResource(*this, &mImage);
@@ -49,7 +49,7 @@
                               const gl::PixelUnpackState &unpack,
                               const uint8_t *pixels)
 {
-    ContextVk *contextVk = GetImplAs<ContextVk>(context);
+    ContextVk *contextVk = vk::GetImpl(context);
     RendererVk *renderer = contextVk->getRenderer();
 
     // TODO(jmadill): support multi-level textures.
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
index 309766a..02c24ad 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -40,7 +40,7 @@
 
     // Invalidate current pipeline.
     // TODO(jmadill): Use pipeline cache.
-    auto contextVk = GetImplAs<ContextVk>(context);
+    auto contextVk = vk::GetImpl(context);
     contextVk->invalidateCurrentPipeline();
 
     // Invalidate the vertex descriptions.
@@ -67,7 +67,7 @@
 
             if (bufferGL)
             {
-                BufferVk *bufferVk                            = GetImplAs<BufferVk>(bufferGL);
+                BufferVk *bufferVk                            = vk::GetImpl(bufferGL);
                 mCurrentVkBuffersCache[attribIndex]           = bufferVk;
                 mCurrentVertexBufferHandlesCache[attribIndex] = bufferVk->getVkBuffer().getHandle();
             }
diff --git a/src/libANGLE/renderer/vulkan/renderervk_utils.h b/src/libANGLE/renderer/vulkan/renderervk_utils.h
index 500b3d6..0d4b2d8 100644
--- a/src/libANGLE/renderer/vulkan/renderervk_utils.h
+++ b/src/libANGLE/renderer/vulkan/renderervk_utils.h
@@ -19,17 +19,38 @@
 #include "libANGLE/Error.h"
 #include "libANGLE/renderer/renderer_utils.h"
 
+#define ANGLE_GL_OBJECTS_X(PROC) \
+    PROC(Buffer)                 \
+    PROC(Context)                \
+    PROC(Framebuffer)            \
+    PROC(Program)                \
+    PROC(Texture)                \
+    PROC(VertexArray)
+
+#define ANGLE_PRE_DECLARE_OBJECT(OBJ) class OBJ;
+
+namespace egl
+{
+class Display;
+}
+
 namespace gl
 {
 struct Box;
 struct Extents;
 struct RasterizerState;
 struct Rectangle;
+
+ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_OBJECT);
 }
 
+#define ANGLE_PRE_DECLARE_VK_OBJECT(OBJ) class OBJ##Vk;
+
 namespace rx
 {
-class ContextVk;
+class DisplayVk;
+
+ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_VK_OBJECT);
 
 const char *VulkanResultString(VkResult result);
 bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps);
@@ -66,6 +87,35 @@
 
 namespace vk
 {
+template <typename T>
+struct ImplTypeHelper;
+
+// clang-format off
+#define ANGLE_IMPL_TYPE_HELPER_GL(OBJ) \
+template<>                             \
+struct ImplTypeHelper<gl::OBJ>         \
+{                                      \
+    using ImplType = OBJ##Vk;          \
+};
+// clang-format on
+
+ANGLE_GL_OBJECTS_X(ANGLE_IMPL_TYPE_HELPER_GL)
+
+template <>
+struct ImplTypeHelper<egl::Display>
+{
+    using ImplType = DisplayVk;
+};
+
+template <typename T>
+using GetImplType = typename ImplTypeHelper<T>::ImplType;
+
+template <typename T>
+GetImplType<T> *GetImpl(const T *glObject)
+{
+    return GetImplAs<GetImplType<T>>(glObject);
+}
+
 class MemoryProperties final : angle::NonCopyable
 {
   public: