зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
2197dc5290
Коммит
502d2e2155
|
@ -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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче