Vulkan: Implement basic Renderbuffer attachments.
Creating an ImageView for color Renderbuffers allows us to render to
them in a RenderPass. We will also need additional functionality to
support depth/stencil Renderbuffers.
Bug: angleproject:2347
Change-Id: I5d4f7d8242ad4fbca38cb08c0cf6b43edca57c8f
Reviewed-on: https://chromium-review.googlesource.com/922456
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
index d87747b..6d8d113 100644
--- a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
@@ -31,6 +31,7 @@
renderer->releaseResource(*this, &mImage);
renderer->releaseResource(*this, &mDeviceMemory);
+ renderer->releaseResource(*this, &mImageView);
return gl::NoError();
}
@@ -42,6 +43,7 @@
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
const vk::Format &vkFormat = renderer->getFormat(internalformat);
+ VkDevice device = renderer->getDevice();
VkImageUsageFlags usage =
(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
@@ -66,10 +68,43 @@
imageInfo.pQueueFamilyIndices = nullptr;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- ANGLE_TRY(mImage.init(contextVk->getDevice(), imageInfo));
+ ANGLE_TRY(mImage.init(device, imageInfo));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(vk::AllocateImageMemory(renderer, flags, &mImage, &mDeviceMemory, &mRequiredSize));
+
+ VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
+
+ // Allocate ImageView.
+ VkImageViewCreateInfo viewInfo;
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.pNext = nullptr;
+ viewInfo.flags = 0;
+ viewInfo.image = mImage.getHandle();
+ viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = vkFormat.vkTextureFormat;
+ viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ viewInfo.subresourceRange.aspectMask = aspect;
+ viewInfo.subresourceRange.baseMipLevel = 0;
+ viewInfo.subresourceRange.levelCount = 1;
+ viewInfo.subresourceRange.baseArrayLayer = 0;
+ viewInfo.subresourceRange.layerCount = 1;
+
+ ANGLE_TRY(mImageView.init(device, viewInfo));
+
+ // Init RenderTarget.
+ mRenderTarget.extents.width = static_cast<int>(width);
+ mRenderTarget.extents.height = static_cast<int>(height);
+ mRenderTarget.extents.depth = 1;
+ mRenderTarget.format = &vkFormat;
+ mRenderTarget.image = &mImage;
+ mRenderTarget.imageView = &mImageView;
+ mRenderTarget.resource = this;
+ mRenderTarget.samples = VK_SAMPLE_COUNT_1_BIT; // TODO(jmadill): Multisample bits.
+
return gl::NoError();
}
@@ -89,13 +124,14 @@
return gl::InternalError();
}
-gl::Error RenderbufferVk::getAttachmentRenderTarget(const gl::Context *context,
- GLenum binding,
- const gl::ImageIndex &imageIndex,
+gl::Error RenderbufferVk::getAttachmentRenderTarget(const gl::Context * /*context*/,
+ GLenum /*binding*/,
+ const gl::ImageIndex & /*imageIndex*/,
FramebufferAttachmentRenderTarget **rtOut)
{
- UNIMPLEMENTED();
- return gl::InternalError();
+ ASSERT(mImage.valid());
+ *rtOut = &mRenderTarget;
+ return gl::NoError();
}
gl::Error RenderbufferVk::initializeContents(const gl::Context *context,
diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.h b/src/libANGLE/renderer/vulkan/RenderbufferVk.h
index 7ef0e17..ac4d8a8 100644
--- a/src/libANGLE/renderer/vulkan/RenderbufferVk.h
+++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.h
@@ -11,6 +11,7 @@
#define LIBANGLE_RENDERER_VULKAN_RENDERBUFFERVK_H_
#include "libANGLE/renderer/RenderbufferImpl.h"
+#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
@@ -46,7 +47,9 @@
private:
vk::Image mImage;
vk::DeviceMemory mDeviceMemory;
+ vk::ImageView mImageView;
size_t mRequiredSize;
+ RenderTargetVk mRenderTarget;
};
} // namespace rx
diff --git a/src/tests/gl_tests/SimpleOperationTest.cpp b/src/tests/gl_tests/SimpleOperationTest.cpp
index befaa65..3e99b84 100644
--- a/src/tests/gl_tests/SimpleOperationTest.cpp
+++ b/src/tests/gl_tests/SimpleOperationTest.cpp
@@ -762,6 +762,29 @@
ASSERT_GL_NO_ERROR();
}
+// Render to a simple color Renderbuffer.
+TEST_P(SimpleOperationTest, RenderbufferAttachment)
+{
+ constexpr int kSize = 16;
+
+ GLRenderbuffer renderbuffer;
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
+
+ GLFramebuffer framebuffer;
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
+ ASSERT_GL_NO_ERROR();
+ ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ glViewport(0, 0, kSize, kSize);
+
+ ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
+ 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(),