Commit ab9f9c31 by Jamie Madill Committed by Commit Bot

Vulkan: Configure a simple RenderPass for drawing.

BUG=angleproject:1319 Change-Id: I0668527a338a2f10ca74b43f2a8bd82534e732c0 Reviewed-on: https://chromium-review.googlesource.com/370805 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent e70413c7
...@@ -72,10 +72,10 @@ class FramebufferImpl : angle::NonCopyable ...@@ -72,10 +72,10 @@ class FramebufferImpl : angle::NonCopyable
virtual void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) = 0; virtual void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) = 0;
const gl::FramebufferState &getState() const { return mState; }
virtual gl::Error getSamplePosition(size_t index, GLfloat *xy) const = 0; virtual gl::Error getSamplePosition(size_t index, GLfloat *xy) const = 0;
const gl::FramebufferState &getState() const { return mState; }
protected: protected:
const gl::FramebufferState &mState; const gl::FramebufferState &mState;
}; };
......
...@@ -38,6 +38,29 @@ gl::ErrorOrResult<const gl::InternalFormat *> GetReadAttachmentInfo( ...@@ -38,6 +38,29 @@ gl::ErrorOrResult<const gl::InternalFormat *> GetReadAttachmentInfo(
return &gl::GetInternalFormatInfo(implFormat); return &gl::GetInternalFormatInfo(implFormat);
} }
VkSampleCountFlagBits ConvertSamples(GLint sampleCount)
{
switch (sampleCount)
{
case 0:
case 1:
return VK_SAMPLE_COUNT_1_BIT;
case 2:
return VK_SAMPLE_COUNT_2_BIT;
case 4:
return VK_SAMPLE_COUNT_4_BIT;
case 8:
return VK_SAMPLE_COUNT_8_BIT;
case 16:
return VK_SAMPLE_COUNT_16_BIT;
case 32:
return VK_SAMPLE_COUNT_32_BIT;
default:
UNREACHABLE();
return VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
}
}
} // anonymous namespace } // anonymous namespace
// static // static
...@@ -53,12 +76,19 @@ FramebufferVk *FramebufferVk::CreateDefaultFBO(const gl::FramebufferState &state ...@@ -53,12 +76,19 @@ FramebufferVk *FramebufferVk::CreateDefaultFBO(const gl::FramebufferState &state
return new FramebufferVk(state, backbuffer); return new FramebufferVk(state, backbuffer);
} }
FramebufferVk::FramebufferVk(const gl::FramebufferState &state) : FramebufferImpl(state) FramebufferVk::FramebufferVk(const gl::FramebufferState &state)
: FramebufferImpl(state),
mBackbuffer(nullptr),
mRenderPass(VK_NULL_HANDLE),
mFramebuffer(VK_NULL_HANDLE)
{ {
} }
FramebufferVk::FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer) FramebufferVk::FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer)
: FramebufferImpl(state) : FramebufferImpl(state),
mBackbuffer(backbuffer),
mRenderPass(VK_NULL_HANDLE),
mFramebuffer(VK_NULL_HANDLE)
{ {
} }
...@@ -294,6 +324,184 @@ bool FramebufferVk::checkStatus() const ...@@ -294,6 +324,184 @@ bool FramebufferVk::checkStatus() const
void FramebufferVk::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) void FramebufferVk::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
{ {
// TODO(jmadill): Smarter update. // TODO(jmadill): Smarter update.
mRenderPass = vk::RenderPass();
mFramebuffer = vk::Framebuffer();
}
gl::ErrorOrResult<vk::RenderPass *> FramebufferVk::getRenderPass(VkDevice device)
{
if (mRenderPass.valid())
{
return &mRenderPass;
}
// TODO(jmadill): Can we use stack-only memory?
std::vector<VkAttachmentDescription> attachmentDescs;
std::vector<VkAttachmentReference> colorAttachmentRefs;
const auto &colorAttachments = mState.getColorAttachments();
for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
{
const auto &colorAttachment = colorAttachments[attachmentIndex];
if (colorAttachment.isAttached())
{
VkAttachmentDescription colorDesc;
VkAttachmentReference colorRef;
RenderTargetVk *renderTarget = nullptr;
ANGLE_TRY(colorAttachment.getRenderTarget(&renderTarget));
// TODO(jmadill): We would only need this flag for duplicated attachments.
colorDesc.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
colorDesc.format = renderTarget->format->native;
colorDesc.samples = ConvertSamples(colorAttachment.getSamples());
// The load op controls the prior existing depth/color attachment data.
// TODO(jmadill): Proper load ops. Should not be hard coded to clear.
colorDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorDesc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
colorRef.attachment = static_cast<uint32_t>(colorAttachments.size()) - 1u;
colorRef.layout = VK_IMAGE_LAYOUT_GENERAL;
attachmentDescs.push_back(colorDesc);
colorAttachmentRefs.push_back(colorRef);
}
}
const auto *depthStencilAttachment = mState.getDepthStencilAttachment();
VkAttachmentReference depthStencilAttachmentRef;
bool useDepth = depthStencilAttachment && depthStencilAttachment->isAttached();
if (useDepth)
{
VkAttachmentDescription depthStencilDesc;
RenderTargetVk *renderTarget = nullptr;
ANGLE_TRY(depthStencilAttachment->getRenderTarget(&renderTarget));
depthStencilDesc.flags = 0;
depthStencilDesc.format = renderTarget->format->native;
depthStencilDesc.samples = ConvertSamples(depthStencilAttachment->getSamples());
depthStencilDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthStencilDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
depthStencilDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthStencilDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthStencilDesc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depthStencilDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depthStencilAttachmentRef.attachment = static_cast<uint32_t>(attachmentDescs.size());
depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachmentDescs.push_back(depthStencilDesc);
}
ASSERT(!attachmentDescs.empty());
VkSubpassDescription subpassDesc;
subpassDesc.flags = 0;
subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDesc.inputAttachmentCount = 0;
subpassDesc.pInputAttachments = nullptr;
subpassDesc.colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
subpassDesc.pColorAttachments = colorAttachmentRefs.data();
subpassDesc.pResolveAttachments = nullptr;
subpassDesc.pDepthStencilAttachment = (useDepth ? &depthStencilAttachmentRef : nullptr);
subpassDesc.preserveAttachmentCount = 0;
subpassDesc.pPreserveAttachments = nullptr;
VkRenderPassCreateInfo renderPassInfo;
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.pNext = nullptr;
renderPassInfo.flags = 0;
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachmentDescs.size());
renderPassInfo.pAttachments = attachmentDescs.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpassDesc;
renderPassInfo.dependencyCount = 0;
renderPassInfo.pDependencies = nullptr;
vk::RenderPass renderPass(device);
ANGLE_TRY(renderPass.init(renderPassInfo));
mRenderPass = std::move(renderPass);
return &mRenderPass;
}
gl::ErrorOrResult<vk::Framebuffer *> FramebufferVk::getFramebuffer(VkDevice device)
{
// If we've already created our cached Framebuffer, return it.
if (mFramebuffer.valid())
{
return &mFramebuffer;
}
vk::RenderPass *renderPass = nullptr;
ANGLE_TRY_RESULT(getRenderPass(device), renderPass);
// If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
if (mBackbuffer)
{
return mBackbuffer->getCurrentFramebuffer(device, *renderPass);
}
// Gather VkImageViews over all FBO attachments, also size of attached region.
std::vector<VkImageView> attachments;
gl::Extents attachmentsSize;
const auto &colorAttachments = mState.getColorAttachments();
for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
{
const auto &colorAttachment = colorAttachments[attachmentIndex];
if (colorAttachment.isAttached())
{
RenderTargetVk *renderTarget = nullptr;
ANGLE_TRY(colorAttachment.getRenderTarget<RenderTargetVk>(&renderTarget));
attachments.push_back(renderTarget->imageView->getHandle());
ASSERT(attachmentsSize.empty() || attachmentsSize == colorAttachment.getSize());
attachmentsSize = colorAttachment.getSize();
}
}
const auto *depthStencilAttachment = mState.getDepthStencilAttachment();
if (depthStencilAttachment && depthStencilAttachment->isAttached())
{
RenderTargetVk *renderTarget = nullptr;
ANGLE_TRY(depthStencilAttachment->getRenderTarget<RenderTargetVk>(&renderTarget));
attachments.push_back(renderTarget->imageView->getHandle());
ASSERT(attachmentsSize.empty() || attachmentsSize == depthStencilAttachment->getSize());
attachmentsSize = depthStencilAttachment->getSize();
}
ASSERT(!attachments.empty());
VkFramebufferCreateInfo framebufferInfo;
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.pNext = nullptr;
framebufferInfo.flags = 0;
framebufferInfo.renderPass = mRenderPass.getHandle();
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
framebufferInfo.pAttachments = attachments.data();
framebufferInfo.width = static_cast<uint32_t>(attachmentsSize.width);
framebufferInfo.height = static_cast<uint32_t>(attachmentsSize.height);
framebufferInfo.layers = 1;
vk::Framebuffer framebuffer(device);
ANGLE_TRY(framebuffer.init(framebufferInfo));
mFramebuffer = std::move(framebuffer);
return &mFramebuffer;
} }
gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const gl::Error FramebufferVk::getSamplePosition(size_t index, GLfloat *xy) const
......
...@@ -75,10 +75,24 @@ class FramebufferVk : public FramebufferImpl ...@@ -75,10 +75,24 @@ class FramebufferVk : public FramebufferImpl
void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override; void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
gl::Error beginRenderPass(VkDevice device,
vk::CommandBuffer *commandBuffer,
const gl::State &glState);
gl::ErrorOrResult<vk::RenderPass *> getRenderPass(VkDevice device);
private: private:
FramebufferVk(const gl::FramebufferState &state); FramebufferVk(const gl::FramebufferState &state);
FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer); FramebufferVk(const gl::FramebufferState &state, WindowSurfaceVk *backbuffer);
gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
gl::ErrorOrResult<vk::Framebuffer *> getFramebuffer(VkDevice device);
WindowSurfaceVk *mBackbuffer;
vk::RenderPass mRenderPass;
vk::Framebuffer mFramebuffer;
}; };
} // namespace rx } // namespace rx
......
...@@ -480,4 +480,43 @@ gl::Error WindowSurfaceVk::getAttachmentRenderTarget( ...@@ -480,4 +480,43 @@ gl::Error WindowSurfaceVk::getAttachmentRenderTarget(
return gl::NoError(); return gl::NoError();
} }
gl::ErrorOrResult<vk::Framebuffer *> WindowSurfaceVk::getCurrentFramebuffer(
VkDevice device,
const vk::RenderPass &compatibleRenderPass)
{
if (!mSwapchainFramebuffers.empty())
{
// Validation layers should detect if the render pass is really compatible.
return &mSwapchainFramebuffers[mCurrentSwapchainImageIndex];
}
VkFramebufferCreateInfo framebufferInfo;
// TODO(jmadill): Depth/Stencil attachments.
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.pNext = nullptr;
framebufferInfo.flags = 0;
framebufferInfo.renderPass = compatibleRenderPass.getHandle();
framebufferInfo.attachmentCount = 1u;
framebufferInfo.pAttachments = nullptr;
framebufferInfo.width = static_cast<uint32_t>(mRenderTarget.extents.width);
framebufferInfo.height = static_cast<uint32_t>(mRenderTarget.extents.height);
framebufferInfo.layers = 1;
for (const auto &imageView : mSwapchainImageViews)
{
VkImageView imageViewHandle = imageView.getHandle();
framebufferInfo.pAttachments = &imageViewHandle;
vk::Framebuffer framebuffer(device);
ANGLE_TRY(framebuffer.init(framebufferInfo));
mSwapchainFramebuffers.push_back(std::move(framebuffer));
}
// We should only initialize framebuffers on the first swap.
ASSERT(mCurrentSwapchainImageIndex == 0u);
return &mSwapchainFramebuffers[mCurrentSwapchainImageIndex];
}
} // namespace rx } // namespace rx
...@@ -78,6 +78,11 @@ class WindowSurfaceVk : public SurfaceImpl ...@@ -78,6 +78,11 @@ class WindowSurfaceVk : public SurfaceImpl
gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
FramebufferAttachmentRenderTarget **rtOut) override; FramebufferAttachmentRenderTarget **rtOut) override;
gl::ErrorOrResult<vk::Framebuffer *> getCurrentFramebuffer(
VkDevice device,
const vk::RenderPass &compatibleRenderPass);
void onBeginRenderPass();
private: private:
vk::Error initializeImpl(RendererVk *renderer); vk::Error initializeImpl(RendererVk *renderer);
vk::Error nextSwapchainImage(RendererVk *renderer); vk::Error nextSwapchainImage(RendererVk *renderer);
...@@ -97,6 +102,7 @@ class WindowSurfaceVk : public SurfaceImpl ...@@ -97,6 +102,7 @@ class WindowSurfaceVk : public SurfaceImpl
uint32_t mCurrentSwapchainImageIndex; uint32_t mCurrentSwapchainImageIndex;
std::vector<vk::Image> mSwapchainImages; std::vector<vk::Image> mSwapchainImages;
std::vector<vk::ImageView> mSwapchainImageViews; std::vector<vk::ImageView> mSwapchainImageViews;
std::vector<vk::Framebuffer> mSwapchainFramebuffers;
}; };
} // namespace rx } // namespace rx
......
...@@ -337,6 +337,35 @@ void CommandBuffer::copySingleImage(const vk::Image &srcImage, ...@@ -337,6 +337,35 @@ void CommandBuffer::copySingleImage(const vk::Image &srcImage,
destImage.getHandle(), destImage.getCurrentLayout(), 1, &region); destImage.getHandle(), destImage.getCurrentLayout(), 1, &region);
} }
void CommandBuffer::beginRenderPass(const RenderPass &renderPass,
const Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const std::vector<VkClearValue> &clearValues)
{
ASSERT(!clearValues.empty());
ASSERT(mHandle != VK_NULL_HANDLE);
VkRenderPassBeginInfo beginInfo;
beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
beginInfo.pNext = nullptr;
beginInfo.renderPass = renderPass.getHandle();
beginInfo.framebuffer = framebuffer.getHandle();
beginInfo.renderArea.offset.x = static_cast<uint32_t>(renderArea.x);
beginInfo.renderArea.offset.y = static_cast<uint32_t>(renderArea.y);
beginInfo.renderArea.extent.width = static_cast<uint32_t>(renderArea.width);
beginInfo.renderArea.extent.height = static_cast<uint32_t>(renderArea.height);
beginInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
beginInfo.pClearValues = clearValues.data();
vkCmdBeginRenderPass(mHandle, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
}
void CommandBuffer::endRenderPass()
{
ASSERT(mHandle != VK_NULL_HANDLE);
vkCmdEndRenderPass(mHandle);
}
// Image implementation. // Image implementation.
Image::Image() : mCurrentLayout(VK_IMAGE_LAYOUT_UNDEFINED) Image::Image() : mCurrentLayout(VK_IMAGE_LAYOUT_UNDEFINED)
{ {
...@@ -621,6 +650,41 @@ void DeviceMemory::unmap() ...@@ -621,6 +650,41 @@ void DeviceMemory::unmap()
vkUnmapMemory(mDevice, mHandle); vkUnmapMemory(mDevice, mHandle);
} }
// RenderPass implementation.
RenderPass::RenderPass()
{
}
RenderPass::RenderPass(VkDevice device) : WrappedObject(device)
{
}
RenderPass::RenderPass(RenderPass &&other) : WrappedObject(std::move(other))
{
}
RenderPass::~RenderPass()
{
if (mHandle != VK_NULL_HANDLE)
{
ASSERT(validDevice());
vkDestroyRenderPass(mDevice, mHandle, nullptr);
}
}
RenderPass &RenderPass::operator=(RenderPass &&other)
{
assignOpBase(std::move(other));
return *this;
}
Error RenderPass::init(const VkRenderPassCreateInfo &createInfo)
{
ASSERT(validDevice() && !valid());
ANGLE_VK_TRY(vkCreateRenderPass(mDevice, &createInfo, nullptr, &mHandle));
return NoError();
}
// StagingImage implementation. // StagingImage implementation.
StagingImage::StagingImage() : mSize(0) StagingImage::StagingImage() : mSize(0)
{ {
......
...@@ -41,6 +41,7 @@ namespace vk ...@@ -41,6 +41,7 @@ namespace vk
class DeviceMemory; class DeviceMemory;
class Framebuffer; class Framebuffer;
class Image; class Image;
class RenderPass;
class Error final class Error final
{ {
...@@ -57,6 +58,11 @@ class Error final ...@@ -57,6 +58,11 @@ class Error final
operator gl::Error() const; operator gl::Error() const;
operator egl::Error() const; operator egl::Error() const;
template <typename T>
operator gl::ErrorOrResult<T>() const
{
return static_cast<gl::Error>(*this);
}
bool isError() const; bool isError() const;
...@@ -115,6 +121,7 @@ class CommandBuffer final : public WrappedObject<VkCommandBuffer> ...@@ -115,6 +121,7 @@ class CommandBuffer final : public WrappedObject<VkCommandBuffer>
Error begin(); Error begin();
Error end(); Error end();
Error reset(); Error reset();
void singleImageBarrier(VkPipelineStageFlags srcStageMask, void singleImageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask, VkPipelineStageFlags dstStageMask,
VkDependencyFlags dependencyFlags, VkDependencyFlags dependencyFlags,
...@@ -127,6 +134,12 @@ class CommandBuffer final : public WrappedObject<VkCommandBuffer> ...@@ -127,6 +134,12 @@ class CommandBuffer final : public WrappedObject<VkCommandBuffer>
const gl::Box &copyRegion, const gl::Box &copyRegion,
VkImageAspectFlags aspectMask); VkImageAspectFlags aspectMask);
void beginRenderPass(const RenderPass &renderPass,
const Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const std::vector<VkClearValue> &clearValues);
void endRenderPass();
private: private:
VkCommandPool mCommandPool; VkCommandPool mCommandPool;
}; };
...@@ -160,6 +173,7 @@ class Image final : public WrappedObject<VkImage> ...@@ -160,6 +173,7 @@ class Image final : public WrappedObject<VkImage>
Error bindMemory(const vk::DeviceMemory &deviceMemory); Error bindMemory(const vk::DeviceMemory &deviceMemory);
VkImageLayout getCurrentLayout() const { return mCurrentLayout; } VkImageLayout getCurrentLayout() const { return mCurrentLayout; }
void updateLayout(VkImageLayout layout) { mCurrentLayout = layout; }
private: private:
VkImageLayout mCurrentLayout; VkImageLayout mCurrentLayout;
...@@ -217,6 +231,18 @@ class DeviceMemory final : public WrappedObject<VkDeviceMemory> ...@@ -217,6 +231,18 @@ class DeviceMemory final : public WrappedObject<VkDeviceMemory>
void unmap(); void unmap();
}; };
class RenderPass final : public WrappedObject<VkRenderPass>
{
public:
RenderPass();
RenderPass(VkDevice device);
RenderPass(RenderPass &&other);
~RenderPass();
RenderPass &operator=(RenderPass &&other);
Error init(const VkRenderPassCreateInfo &createInfo);
};
class StagingImage final : angle::NonCopyable class StagingImage final : angle::NonCopyable
{ {
public: public:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment