Vulkan: Crunch RenderPassDesc.

This reduces the size of the RenderPass desc from 64 to 12 bytes.

Bug: angleproject:2522
Change-Id: Iff2df87ba65be0bd976bba81c76c285cb0fa1ceb
Reviewed-on: https://chromium-review.googlesource.com/c/1308459
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Jamie Madill 2018-11-01 11:06:23 -04:00 коммит произвёл Commit Bot
Родитель 2197dc5290
Коммит 502d2e2155
6 изменённых файлов: 113 добавлений и 114 удалений

Просмотреть файл

@ -10,6 +10,7 @@
#define LIBANGLE_ANGLETYPES_H_
#include "common/Color.h"
#include "common/FixedVector.h"
#include "common/PackedEnums.h"
#include "common/bitset_utils.h"
#include "common/vector_utils.h"
@ -416,6 +417,9 @@ using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS
template <typename T>
using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
template <typename T>
using DrawBuffersVector = angle::FixedVector<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
template <typename T>
using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;

Просмотреть файл

@ -789,6 +789,7 @@ const vk::RenderPassDesc &FramebufferVk::getRenderPassDesc()
}
vk::RenderPassDesc desc;
desc.setSamples(getSamples());
// TODO(jmadill): Support gaps in RenderTargets. http://anglebug.com/2394
const auto &colorRenderTargets = mRenderTargetCache.getColors();
@ -796,13 +797,13 @@ const vk::RenderPassDesc &FramebufferVk::getRenderPassDesc()
{
RenderTargetVk *colorRenderTarget = colorRenderTargets[colorIndex];
ASSERT(colorRenderTarget);
desc.packColorAttachment(colorRenderTarget->getImage());
desc.packAttachment(colorRenderTarget->getImage().getFormat());
}
RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
if (depthStencilRenderTarget)
{
desc.packDepthStencilAttachment(depthStencilRenderTarget->getImage());
desc.packAttachment(depthStencilRenderTarget->getImage().getFormat());
}
mRenderPassDesc = desc;
@ -1223,4 +1224,24 @@ const gl::Extents &FramebufferVk::getReadImageExtents() const
{
return getColorReadRenderTarget()->getImageExtents();
}
RenderTargetVk *FramebufferVk::getFirstRenderTarget() const
{
for (auto *renderTarget : mRenderTargetCache.getColors())
{
if (renderTarget)
{
return renderTarget;
}
}
return mRenderTargetCache.getDepthStencil();
}
GLint FramebufferVk::getSamples() const
{
RenderTargetVk *firstRT = getFirstRenderTarget();
return firstRT ? firstRT->getImage().getSamples() : 0;
}
} // namespace rx

Просмотреть файл

@ -116,6 +116,9 @@ class FramebufferVk : public FramebufferImpl
angle::Result startNewRenderPass(ContextVk *context, vk::CommandBuffer **commandBufferOut);
RenderTargetVk *getFirstRenderTarget() const;
GLint getSamples() const;
private:
FramebufferVk(RendererVk *renderer,
const gl::FramebufferState &state,

Просмотреть файл

@ -39,7 +39,7 @@ void RenderTargetVk::onColorDraw(vk::FramebufferHelper *framebufferVk,
ASSERT(!mImage->getFormat().textureFormat().hasDepthOrStencilBits());
// Store the attachment info in the renderPassDesc.
renderPassDesc->packColorAttachment(*mImage);
renderPassDesc->packAttachment(mImage->getFormat());
// TODO(jmadill): Use automatic layout transition. http://anglebug.com/2361
mImage->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT,
@ -59,7 +59,7 @@ void RenderTargetVk::onDepthStencilDraw(vk::FramebufferHelper *framebufferVk,
ASSERT(mImage->getFormat().textureFormat().hasDepthOrStencilBits());
// Store the attachment info in the renderPassDesc.
renderPassDesc->packDepthStencilAttachment(*mImage);
renderPassDesc->packAttachment(mImage->getFormat());
// TODO(jmadill): Use automatic layout transition. http://anglebug.com/2361
const angle::Format &format = mImage->getFormat().textureFormat();

Просмотреть файл

@ -136,12 +136,14 @@ uint8_t PackGLCompareFunc(GLenum compareFunc)
}
void UnpackAttachmentDesc(VkAttachmentDescription *desc,
const vk::PackedAttachmentDesc &packedDesc,
const vk::Format &format,
uint8_t samples,
const vk::PackedAttachmentOpsDesc &ops)
{
desc->flags = static_cast<VkAttachmentDescriptionFlags>(packedDesc.flags);
desc->format = static_cast<VkFormat>(packedDesc.format);
desc->samples = gl_vk::GetSamples(packedDesc.samples);
// We would only need this flag for duplicated attachments. Apply it conservatively.
desc->flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
desc->format = format.vkTextureFormat;
desc->samples = gl_vk::GetSamples(samples);
desc->loadOp = static_cast<VkAttachmentLoadOp>(ops.loadOp);
desc->storeOp = static_cast<VkAttachmentStoreOp>(ops.storeOp);
desc->stencilLoadOp = static_cast<VkAttachmentLoadOp>(ops.stencilLoadOp);
@ -179,24 +181,35 @@ angle::Result InitializeRenderPassFromDesc(vk::Context *context,
const AttachmentOpsArray &ops,
RenderPass *renderPass)
{
uint32_t attachmentCount = desc.attachmentCount();
ASSERT(attachmentCount > 0);
gl::DrawBuffersArray<VkAttachmentReference> colorAttachmentRefs;
for (uint32_t colorIndex = 0; colorIndex < desc.colorAttachmentCount(); ++colorIndex)
{
VkAttachmentReference &colorRef = colorAttachmentRefs[colorIndex];
colorRef.attachment = colorIndex;
colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
size_t attachmentCount = desc.attachmentCount();
// Unpack the packed and split representation into the format required by Vulkan.
gl::DrawBuffersVector<VkAttachmentReference> colorAttachmentRefs;
VkAttachmentReference depthStencilAttachmentRef = {};
if (desc.depthStencilAttachmentCount() > 0)
gl::AttachmentArray<VkAttachmentDescription> attachmentDescs;
for (uint32_t attachmentIndex = 0; attachmentIndex < attachmentCount; ++attachmentIndex)
{
ASSERT(desc.depthStencilAttachmentCount() == 1);
depthStencilAttachmentRef.attachment = desc.colorAttachmentCount();
depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
angle::FormatID formatID = desc[attachmentIndex];
ASSERT(formatID != angle::FormatID::NONE);
const vk::Format &format = context->getRenderer()->getFormat(formatID);
if (!format.angleFormat().hasDepthOrStencilBits())
{
VkAttachmentReference colorRef = colorAttachmentRefs[attachmentIndex];
colorRef.attachment = attachmentIndex;
colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorAttachmentRefs.push_back(colorRef);
}
else
{
ASSERT(depthStencilAttachmentRef.attachment == 0);
depthStencilAttachmentRef.attachment = attachmentIndex;
depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
}
UnpackAttachmentDesc(&attachmentDescs[attachmentIndex], format, desc.samples(),
ops[attachmentIndex]);
}
VkSubpassDescription subpassDesc = {};
@ -205,28 +218,14 @@ angle::Result InitializeRenderPassFromDesc(vk::Context *context,
subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDesc.inputAttachmentCount = 0;
subpassDesc.pInputAttachments = nullptr;
subpassDesc.colorAttachmentCount = desc.colorAttachmentCount();
subpassDesc.colorAttachmentCount = static_cast<uint32_t>(colorAttachmentRefs.size());
subpassDesc.pColorAttachments = colorAttachmentRefs.data();
subpassDesc.pResolveAttachments = nullptr;
subpassDesc.pDepthStencilAttachment =
(desc.depthStencilAttachmentCount() > 0 ? &depthStencilAttachmentRef : nullptr);
(depthStencilAttachmentRef.attachment > 0 ? &depthStencilAttachmentRef : nullptr);
subpassDesc.preserveAttachmentCount = 0;
subpassDesc.pPreserveAttachments = nullptr;
// Unpack the packed and split representation into the format required by Vulkan.
gl::AttachmentArray<VkAttachmentDescription> attachmentDescs;
for (uint32_t colorIndex = 0; colorIndex < desc.colorAttachmentCount(); ++colorIndex)
{
UnpackAttachmentDesc(&attachmentDescs[colorIndex], desc[colorIndex], ops[colorIndex]);
}
if (desc.depthStencilAttachmentCount() > 0)
{
uint32_t depthStencilIndex = desc.colorAttachmentCount();
UnpackAttachmentDesc(&attachmentDescs[depthStencilIndex], desc[depthStencilIndex],
ops[depthStencilIndex]);
}
VkRenderPassCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
createInfo.flags = 0;
@ -246,7 +245,6 @@ angle::Result InitializeRenderPassFromDesc(vk::Context *context,
// RenderPassDesc implementation.
RenderPassDesc::RenderPassDesc()
{
ANGLE_UNUSED_VARIABLE(mPadding);
memset(this, 0, sizeof(RenderPassDesc));
}
@ -257,30 +255,23 @@ RenderPassDesc::RenderPassDesc(const RenderPassDesc &other)
memcpy(this, &other, sizeof(RenderPassDesc));
}
void RenderPassDesc::packAttachment(uint32_t index, const ImageHelper &imageHelper)
size_t RenderPassDesc::attachmentCount() const
{
PackedAttachmentDesc &desc = mAttachmentDescs[index];
// TODO(jmadill): We would only need this flag for duplicated attachments.
desc.flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
ASSERT(imageHelper.getSamples() < std::numeric_limits<uint8_t>::max());
desc.samples = static_cast<uint8_t>(imageHelper.getSamples());
const Format &format = imageHelper.getFormat();
ASSERT(format.vkTextureFormat < std::numeric_limits<uint16_t>::max());
desc.format = static_cast<uint16_t>(format.vkTextureFormat);
return mAttachmentCount;
}
void RenderPassDesc::packColorAttachment(const ImageHelper &imageHelper)
void RenderPassDesc::setSamples(GLint samples)
{
ASSERT(mDepthStencilAttachmentCount == 0);
ASSERT(mColorAttachmentCount < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
packAttachment(mColorAttachmentCount++, imageHelper);
ASSERT(samples < std::numeric_limits<uint8_t>::max());
mSamples = static_cast<uint8_t>(samples);
}
void RenderPassDesc::packDepthStencilAttachment(const ImageHelper &imageHelper)
void RenderPassDesc::packAttachment(const Format &format)
{
ASSERT(mDepthStencilAttachmentCount == 0);
packAttachment(mColorAttachmentCount + mDepthStencilAttachmentCount++, imageHelper);
ASSERT(mAttachmentCount < mAttachmentFormats.size() - 1);
static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
"Too many ANGLE formats to fit in uint8_t");
mAttachmentFormats[mAttachmentCount++] = static_cast<uint8_t>(format.angleFormatID);
}
RenderPassDesc &RenderPassDesc::operator=(const RenderPassDesc &other)
@ -294,27 +285,6 @@ size_t RenderPassDesc::hash() const
return angle::ComputeGenericHash(*this);
}
uint32_t RenderPassDesc::attachmentCount() const
{
return (mColorAttachmentCount + mDepthStencilAttachmentCount);
}
uint32_t RenderPassDesc::colorAttachmentCount() const
{
return mColorAttachmentCount;
}
uint32_t RenderPassDesc::depthStencilAttachmentCount() const
{
return mDepthStencilAttachmentCount;
}
const PackedAttachmentDesc &RenderPassDesc::operator[](size_t index) const
{
ASSERT(index < mAttachmentDescs.size());
return mAttachmentDescs[index];
}
bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs)
{
return (memcmp(&lhs, &rhs, sizeof(RenderPassDesc)) == 0);
@ -334,6 +304,7 @@ void PipelineDesc::operator delete(void *ptr)
PipelineDesc::PipelineDesc()
{
ANGLE_UNUSED_VARIABLE(mPadding);
memset(this, 0, sizeof(PipelineDesc));
}
@ -1038,19 +1009,24 @@ angle::Result RenderPassCache::getCompatibleRenderPass(vk::Context *context,
}
// Insert some dummy attachment ops.
// TODO(jmadill): Pre-populate the cache in the Renderer so we rarely miss here.
// It would be nice to pre-populate the cache in the Renderer so we rarely miss here.
vk::AttachmentOpsArray ops;
for (uint32_t colorIndex = 0; colorIndex < desc.colorAttachmentCount(); ++colorIndex)
{
ops.initDummyOp(colorIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
}
if (desc.depthStencilAttachmentCount() > 0)
for (uint32_t attachmentIndex = 0; attachmentIndex < desc.attachmentCount(); ++attachmentIndex)
{
ops.initDummyOp(desc.colorAttachmentCount(),
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
angle::FormatID formatID = desc[attachmentIndex];
ASSERT(formatID != angle::FormatID::NONE);
const vk::Format &format = context->getRenderer()->getFormat(formatID);
if (!format.angleFormat().hasDepthOrStencilBits())
{
ops.initDummyOp(attachmentIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
}
else
{
ops.initDummyOp(attachmentIndex, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
}
return getRenderPassWithOps(context, serial, desc, ops, renderPassOut);

Просмотреть файл

@ -48,16 +48,7 @@ using SharedPipelineLayout = RefCounted<PipelineLayout>;
// Enable struct padding warnings for the code below since it is used in caches.
ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
struct alignas(4) PackedAttachmentDesc
{
uint8_t flags;
uint8_t samples;
uint16_t format;
};
static_assert(sizeof(PackedAttachmentDesc) == 4, "Size check failed");
class RenderPassDesc final
class alignas(4) RenderPassDesc final
{
public:
RenderPassDesc();
@ -65,29 +56,31 @@ class RenderPassDesc final
RenderPassDesc(const RenderPassDesc &other);
RenderPassDesc &operator=(const RenderPassDesc &other);
// Depth stencil attachments must be packed after color attachments.
void packColorAttachment(const ImageHelper &imageHelper);
void packDepthStencilAttachment(const ImageHelper &imageHelper);
void packAttachment(const Format &format);
size_t hash() const;
uint32_t attachmentCount() const;
uint32_t colorAttachmentCount() const;
uint32_t depthStencilAttachmentCount() const;
const PackedAttachmentDesc &operator[](size_t index) const;
size_t attachmentCount() const;
void setSamples(GLint samples);
uint8_t samples() const { return mSamples; }
angle::FormatID operator[](size_t index) const
{
ASSERT(index < mAttachmentFormats.size());
return static_cast<angle::FormatID>(mAttachmentFormats[index]);
}
private:
void packAttachment(uint32_t index, const ImageHelper &imageHelper);
uint32_t mColorAttachmentCount;
uint32_t mDepthStencilAttachmentCount;
gl::AttachmentArray<PackedAttachmentDesc> mAttachmentDescs;
uint32_t mPadding[4];
uint8_t mSamples;
uint8_t mAttachmentCount;
gl::AttachmentArray<uint8_t> mAttachmentFormats;
};
bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs);
static_assert(sizeof(RenderPassDesc) == 64, "Size check failed");
static_assert(sizeof(RenderPassDesc) == 12, "Size check failed");
struct alignas(8) PackedAttachmentOpsDesc final
{
@ -358,6 +351,7 @@ class PipelineDesc final
// TODO(jmadill): Dynamic state.
// TODO(jmadill): Pipeline layout
RenderPassDesc mRenderPassDesc;
uint8_t mPadding[20];
};
// Verify the packed pipeline description has no gaps in the packing.
@ -369,9 +363,10 @@ constexpr size_t kPipelineDescSumOfSizes =
sizeof(PackedInputAssemblyInfo) + sizeof(VkViewport) + sizeof(VkRect2D) +
sizeof(PackedRasterizationStateInfo) + sizeof(PackedMultisampleStateInfo) +
sizeof(PackedDepthStencilStateInfo) + sizeof(PackedColorBlendStateInfo) +
sizeof(RenderPassDesc);
sizeof(RenderPassDesc) + 20;
static_assert(sizeof(PipelineDesc) == kPipelineDescSumOfSizes, "Size mismatch");
static constexpr size_t kPipelineDescSize = sizeof(PipelineDesc);
static_assert(kPipelineDescSize == kPipelineDescSumOfSizes, "Size mismatch");
constexpr uint32_t kMaxDescriptorSetLayoutBindings = gl::IMPLEMENTATION_MAX_ACTIVE_TEXTURES;