зеркало из https://github.com/AvaloniaUI/angle.git
Vulkan: Use render pass ops to clear images when possible
On tiling GPUs, render pass loadOp and stencilLoadOp can be used to very cheaply clear an image as it is being render to. This change uses this feature to clear render targets when possible. Bug: angleproject:2361 Change-Id: Ic4bdc908873f4802760d549f4893f84a47beac0f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1500576 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Родитель
9049d3217f
Коммит
0c128e15be
|
@ -71,6 +71,10 @@ struct FeaturesVk
|
|||
|
||||
// VK_PRESENT_MODE_FIFO_KHR causes random timeouts on Linux Intel. http://anglebug.com/3153
|
||||
bool disableFifoPresentMode = false;
|
||||
|
||||
// On Qualcomm, a bug is preventing us from using this optimization with inline commands in the
|
||||
// render pass. http://anglebug.com/2361
|
||||
bool disableClearWithRenderPassLoadOp = false;
|
||||
};
|
||||
|
||||
inline FeaturesVk::FeaturesVk() = default;
|
||||
|
|
|
@ -216,12 +216,14 @@ const gl::Rectangle &CommandGraphResource::getRenderPassRenderArea() const
|
|||
return mCurrentWritingNode->getRenderPassRenderArea();
|
||||
}
|
||||
|
||||
angle::Result CommandGraphResource::beginRenderPass(ContextVk *contextVk,
|
||||
const Framebuffer &framebuffer,
|
||||
const gl::Rectangle &renderArea,
|
||||
const RenderPassDesc &renderPassDesc,
|
||||
const std::vector<VkClearValue> &clearValues,
|
||||
CommandBuffer **commandBufferOut)
|
||||
angle::Result CommandGraphResource::beginRenderPass(
|
||||
ContextVk *contextVk,
|
||||
const Framebuffer &framebuffer,
|
||||
const gl::Rectangle &renderArea,
|
||||
const RenderPassDesc &renderPassDesc,
|
||||
const AttachmentOpsArray &renderPassAttachmentOps,
|
||||
const std::vector<VkClearValue> &clearValues,
|
||||
CommandBuffer **commandBufferOut)
|
||||
{
|
||||
// If a barrier has been inserted in the meantime, stop the command buffer.
|
||||
if (!hasChildlessWritingNode())
|
||||
|
@ -229,9 +231,8 @@ angle::Result CommandGraphResource::beginRenderPass(ContextVk *contextVk,
|
|||
startNewCommands(contextVk->getRenderer());
|
||||
}
|
||||
|
||||
// Hard-code RenderPass to clear the first render target to the current clear value.
|
||||
// TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
|
||||
mCurrentWritingNode->storeRenderPassInfo(framebuffer, renderArea, renderPassDesc, clearValues);
|
||||
mCurrentWritingNode->storeRenderPassInfo(framebuffer, renderArea, renderPassDesc,
|
||||
renderPassAttachmentOps, clearValues);
|
||||
|
||||
mCurrentWritingNode->setCommandBufferOwner(contextVk);
|
||||
|
||||
|
@ -376,9 +377,11 @@ angle::Result CommandGraphNode::beginInsideRenderPassRecording(Context *context,
|
|||
void CommandGraphNode::storeRenderPassInfo(const Framebuffer &framebuffer,
|
||||
const gl::Rectangle renderArea,
|
||||
const vk::RenderPassDesc &renderPassDesc,
|
||||
const AttachmentOpsArray &renderPassAttachmentOps,
|
||||
const std::vector<VkClearValue> &clearValues)
|
||||
{
|
||||
mRenderPassDesc = renderPassDesc;
|
||||
mRenderPassDesc = renderPassDesc;
|
||||
mRenderPassAttachmentOps = renderPassAttachmentOps;
|
||||
mRenderPassFramebuffer.setHandle(framebuffer.getHandle());
|
||||
mRenderPassRenderArea = renderArea;
|
||||
std::copy(clearValues.begin(), clearValues.end(), mRenderPassClearValues.begin());
|
||||
|
@ -509,11 +512,12 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
|
|||
|
||||
if (mInsideRenderPassCommands.valid())
|
||||
{
|
||||
// Pull a compatible RenderPass from the cache.
|
||||
// TODO(jmadill): Insert real ops and layout transitions.
|
||||
// Pull a RenderPass from the cache.
|
||||
// TODO(jmadill): Insert layout transitions.
|
||||
RenderPass *renderPass = nullptr;
|
||||
ANGLE_TRY(renderPassCache->getCompatibleRenderPass(context, serial, mRenderPassDesc,
|
||||
&renderPass));
|
||||
ANGLE_TRY(renderPassCache->getRenderPassWithOps(
|
||||
context, serial, mRenderPassDesc, mRenderPassAttachmentOps, &renderPass));
|
||||
|
||||
ANGLE_VK_TRY(context, mInsideRenderPassCommands.end());
|
||||
|
||||
VkRenderPassBeginInfo beginInfo = {};
|
||||
|
|
|
@ -98,6 +98,7 @@ class CommandGraphNode final : angle::NonCopyable
|
|||
void storeRenderPassInfo(const Framebuffer &framebuffer,
|
||||
const gl::Rectangle renderArea,
|
||||
const vk::RenderPassDesc &renderPassDesc,
|
||||
const AttachmentOpsArray &renderPassAttachmentOps,
|
||||
const std::vector<VkClearValue> &clearValues);
|
||||
|
||||
// Dependency commands order node execution in the command graph.
|
||||
|
@ -177,6 +178,7 @@ class CommandGraphNode final : angle::NonCopyable
|
|||
|
||||
// Only used if we need a RenderPass for these commands.
|
||||
RenderPassDesc mRenderPassDesc;
|
||||
AttachmentOpsArray mRenderPassAttachmentOps;
|
||||
Framebuffer mRenderPassFramebuffer;
|
||||
gl::Rectangle mRenderPassRenderArea;
|
||||
gl::AttachmentArray<VkClearValue> mRenderPassClearValues;
|
||||
|
@ -268,6 +270,7 @@ class CommandGraphResource : angle::NonCopyable
|
|||
const Framebuffer &framebuffer,
|
||||
const gl::Rectangle &renderArea,
|
||||
const RenderPassDesc &renderPassDesc,
|
||||
const AttachmentOpsArray &renderPassAttachmentOps,
|
||||
const std::vector<VkClearValue> &clearValues,
|
||||
CommandBuffer **commandBufferOut);
|
||||
|
||||
|
|
|
@ -217,11 +217,38 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
|
|||
}
|
||||
}
|
||||
|
||||
// If scissor is enabled, but covers the whole of framebuffer, it can be considered disabled for
|
||||
// the sake of clear.
|
||||
const gl::Rectangle &scissorRect = glState.getScissor();
|
||||
const gl::Rectangle renderArea(0, 0, mState.getDimensions().width,
|
||||
mState.getDimensions().height);
|
||||
bool isScissorTestEffectivelyEnabled =
|
||||
glState.isScissorTestEnabled() && scissorRect != renderArea;
|
||||
|
||||
// We can use render pass load ops if clearing depth/stencil or unmasked color. If there's a
|
||||
// depth mask, depth clearing is disabled. If there's a stencil mask, the clear value is
|
||||
// already masked. There is no depth/stencil condition prohibiting the use of render pass
|
||||
// loadOp.
|
||||
VkColorComponentFlags colorMaskFlags = contextVk->getClearColorMask();
|
||||
bool maskedClearColor =
|
||||
clearColor && (mActiveColorComponents & colorMaskFlags) != mActiveColorComponents;
|
||||
|
||||
if (!maskedClearColor && !isScissorTestEffectivelyEnabled &&
|
||||
!contextVk->getRenderer()->getFeatures().disableClearWithRenderPassLoadOp)
|
||||
{
|
||||
// Note(syoussefi): A possible optimization could be to allow depth/stencil clear in
|
||||
// presence of color mask, and leave the color clear to the following steps, i.e. start a
|
||||
// render pass with depth/stencil = Clear and have a subsequent draw call within the render
|
||||
// pass to clear the color. That could render some of the depth/stencil clear paths below
|
||||
// unnecessary.
|
||||
return clearWithRenderPassOp(contextVk, clearColor, clearDepth, clearStencil,
|
||||
contextVk->getClearColorValue().color, clearDepthStencilValue);
|
||||
}
|
||||
|
||||
// The most costly clear mode is when we need to mask out specific color channels. This can
|
||||
// only be done with a draw call. The scissor region however can easily be integrated with
|
||||
// this method. Similarly for depth/stencil clear.
|
||||
VkColorComponentFlags colorMaskFlags = contextVk->getClearColorMask();
|
||||
if (clearColor && (mActiveColorComponents & colorMaskFlags) != mActiveColorComponents)
|
||||
if (maskedClearColor)
|
||||
{
|
||||
ANGLE_TRY(clearWithDraw(contextVk, colorMaskFlags));
|
||||
|
||||
|
@ -239,7 +266,7 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
|
|||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
if (glState.isScissorTestEnabled())
|
||||
if (isScissorTestEffectivelyEnabled)
|
||||
{
|
||||
// With scissor test enabled, we clear very differently and we don't need to access
|
||||
// the image inside each attachment we can just use clearCmdAttachments with our
|
||||
|
@ -842,14 +869,14 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, vk::Framebuffe
|
|||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
vk::RenderPass *renderPass = nullptr;
|
||||
ANGLE_TRY(
|
||||
contextVk->getRenderer()->getCompatibleRenderPass(contextVk, mRenderPassDesc, &renderPass));
|
||||
vk::RenderPass *compatibleRenderPass = nullptr;
|
||||
ANGLE_TRY(contextVk->getRenderer()->getCompatibleRenderPass(contextVk, mRenderPassDesc,
|
||||
&compatibleRenderPass));
|
||||
|
||||
// If we've a Framebuffer provided by a Surface (default FBO/backbuffer), query it.
|
||||
if (mBackbuffer)
|
||||
{
|
||||
return mBackbuffer->getCurrentFramebuffer(contextVk, *renderPass, framebufferOut);
|
||||
return mBackbuffer->getCurrentFramebuffer(contextVk, *compatibleRenderPass, framebufferOut);
|
||||
}
|
||||
|
||||
// Gather VkImageViews over all FBO attachments, also size of attached region.
|
||||
|
@ -884,7 +911,7 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, vk::Framebuffe
|
|||
|
||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
framebufferInfo.flags = 0;
|
||||
framebufferInfo.renderPass = renderPass->getHandle();
|
||||
framebufferInfo.renderPass = compatibleRenderPass->getHandle();
|
||||
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
|
||||
framebufferInfo.pAttachments = attachments.data();
|
||||
framebufferInfo.width = static_cast<uint32_t>(attachmentsSize.width);
|
||||
|
@ -897,6 +924,19 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, vk::Framebuffe
|
|||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
angle::Result FramebufferVk::clearWithRenderPassOp(
|
||||
ContextVk *contextVk,
|
||||
bool clearColor,
|
||||
bool clearDepth,
|
||||
bool clearStencil,
|
||||
const VkClearColorValue &clearColorValue,
|
||||
const VkClearDepthStencilValue &clearDepthStencilValue)
|
||||
{
|
||||
vk::CommandBuffer *commandBuffer;
|
||||
return startNewRenderPassImpl(contextVk, clearColor, clearDepth, clearStencil, clearColorValue,
|
||||
clearDepthStencilValue, &commandBuffer);
|
||||
}
|
||||
|
||||
angle::Result FramebufferVk::clearWithClearAttachments(
|
||||
ContextVk *contextVk,
|
||||
bool clearColor,
|
||||
|
@ -1055,16 +1095,35 @@ angle::Result FramebufferVk::getCommandBufferForDraw(ContextVk *contextVk,
|
|||
|
||||
angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
|
||||
vk::CommandBuffer **commandBufferOut)
|
||||
{
|
||||
VkClearColorValue unusedColor = {};
|
||||
VkClearDepthStencilValue unusedDepthStencil = {};
|
||||
|
||||
return startNewRenderPassImpl(contextVk, false, false, false, unusedColor, unusedDepthStencil,
|
||||
commandBufferOut);
|
||||
}
|
||||
|
||||
angle::Result FramebufferVk::startNewRenderPassImpl(
|
||||
ContextVk *contextVk,
|
||||
bool clearColor,
|
||||
bool clearDepth,
|
||||
bool clearStencil,
|
||||
const VkClearColorValue &clearColorValue,
|
||||
const VkClearDepthStencilValue &clearDepthStencilValue,
|
||||
vk::CommandBuffer **commandBufferOut)
|
||||
{
|
||||
vk::Framebuffer *framebuffer = nullptr;
|
||||
ANGLE_TRY(getFramebuffer(contextVk, &framebuffer));
|
||||
|
||||
// TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
|
||||
vk::AttachmentOpsArray renderPassAttachmentOps;
|
||||
std::vector<VkClearValue> attachmentClearValues;
|
||||
|
||||
vk::CommandBuffer *writeCommands = nullptr;
|
||||
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &writeCommands));
|
||||
|
||||
VkClearValue clearValue;
|
||||
clearValue.color = clearColorValue;
|
||||
|
||||
vk::RenderPassDesc renderPassDesc;
|
||||
|
||||
// Initialize RenderPass info.
|
||||
|
@ -1076,21 +1135,58 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
|
|||
ASSERT(colorRenderTarget);
|
||||
|
||||
colorRenderTarget->onColorDraw(&mFramebuffer, writeCommands, &renderPassDesc);
|
||||
attachmentClearValues.emplace_back(contextVk->getClearColorValue());
|
||||
|
||||
VkAttachmentLoadOp colorLoadOp =
|
||||
clearColor ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
|
||||
renderPassAttachmentOps.setLayout(attachmentClearValues.size(),
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
renderPassAttachmentOps.setLoadOp(attachmentClearValues.size(), colorLoadOp,
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||
renderPassAttachmentOps.setStoreOp(attachmentClearValues.size(),
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE);
|
||||
|
||||
// If the render target doesn't have alpha, but its emulated format has it, clear the alpha
|
||||
// to 1.
|
||||
VkClearValue value = clearValue;
|
||||
if (mEmulatedAlphaAttachmentMask[colorIndex])
|
||||
{
|
||||
value.color.float32[3] = 1.0;
|
||||
}
|
||||
|
||||
attachmentClearValues.emplace_back(value);
|
||||
}
|
||||
|
||||
RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
|
||||
if (depthStencilRenderTarget)
|
||||
{
|
||||
depthStencilRenderTarget->onDepthStencilDraw(&mFramebuffer, writeCommands, &renderPassDesc);
|
||||
attachmentClearValues.emplace_back(contextVk->getClearDepthStencilValue());
|
||||
|
||||
VkAttachmentLoadOp depthLoadOp =
|
||||
clearDepth ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
VkAttachmentLoadOp stencilLoadOp =
|
||||
clearStencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
|
||||
renderPassAttachmentOps.setLayout(attachmentClearValues.size(),
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
renderPassAttachmentOps.setLoadOp(attachmentClearValues.size(), depthLoadOp, stencilLoadOp);
|
||||
renderPassAttachmentOps.setStoreOp(attachmentClearValues.size(),
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_ATTACHMENT_STORE_OP_STORE);
|
||||
|
||||
clearValue.depthStencil = clearDepthStencilValue;
|
||||
attachmentClearValues.emplace_back(clearValue);
|
||||
}
|
||||
|
||||
gl::Rectangle renderArea =
|
||||
gl::Rectangle(0, 0, mState.getDimensions().width, mState.getDimensions().height);
|
||||
|
||||
return mFramebuffer.beginRenderPass(contextVk, *framebuffer, renderArea, mRenderPassDesc,
|
||||
attachmentClearValues, commandBufferOut);
|
||||
renderPassAttachmentOps, attachmentClearValues,
|
||||
commandBufferOut);
|
||||
}
|
||||
|
||||
void FramebufferVk::updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a)
|
||||
|
|
|
@ -125,6 +125,14 @@ class FramebufferVk : public FramebufferImpl
|
|||
const gl::FramebufferState &state,
|
||||
WindowSurfaceVk *backbuffer);
|
||||
|
||||
angle::Result startNewRenderPassImpl(ContextVk *context,
|
||||
bool clearColor,
|
||||
bool clearDepth,
|
||||
bool clearStencil,
|
||||
const VkClearColorValue &clearColorValue,
|
||||
const VkClearDepthStencilValue &clearDepthStencilValue,
|
||||
vk::CommandBuffer **commandBufferOut);
|
||||
|
||||
// Helper for appendToStarted/else startNewRenderPass.
|
||||
angle::Result getCommandBufferForDraw(ContextVk *contextVk,
|
||||
vk::CommandBuffer **commandBufferOut,
|
||||
|
@ -159,6 +167,12 @@ class FramebufferVk : public FramebufferImpl
|
|||
|
||||
angle::Result getFramebuffer(ContextVk *contextVk, vk::Framebuffer **framebufferOut);
|
||||
|
||||
angle::Result clearWithRenderPassOp(ContextVk *contextVk,
|
||||
bool clearColor,
|
||||
bool clearDepth,
|
||||
bool clearStencil,
|
||||
const VkClearColorValue &clearColorValue,
|
||||
const VkClearDepthStencilValue &clearDepthStencilValue);
|
||||
angle::Result clearWithClearAttachments(ContextVk *contextVk,
|
||||
bool clearColor,
|
||||
bool clearDepth,
|
||||
|
|
|
@ -1217,6 +1217,11 @@ void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames)
|
|||
{
|
||||
mFeatures.disableFifoPresentMode = true;
|
||||
}
|
||||
|
||||
if (IsAndroid() && IsQualcomm(mPhysicalDeviceProperties.vendorID))
|
||||
{
|
||||
mFeatures.disableClearWithRenderPassLoadOp = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RendererVk::initPipelineCacheVkKey()
|
||||
|
|
|
@ -581,14 +581,15 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
|
|||
{
|
||||
RendererVk *renderer = contextVk->getRenderer();
|
||||
|
||||
vk::RenderPass *renderPass = nullptr;
|
||||
ANGLE_TRY(renderer->getCompatibleRenderPass(contextVk, renderPassDesc, &renderPass));
|
||||
vk::RenderPass *compatibleRenderPass = nullptr;
|
||||
ANGLE_TRY(renderer->getCompatibleRenderPass(contextVk, renderPassDesc, &compatibleRenderPass));
|
||||
|
||||
VkFramebufferCreateInfo framebufferInfo = {};
|
||||
|
||||
// Minimize the framebuffer coverage to only cover up to the render area.
|
||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
framebufferInfo.flags = 0;
|
||||
framebufferInfo.renderPass = renderPass->getHandle();
|
||||
framebufferInfo.renderPass = compatibleRenderPass->getHandle();
|
||||
framebufferInfo.attachmentCount = 1;
|
||||
framebufferInfo.pAttachments = imageView->ptr();
|
||||
framebufferInfo.width = renderArea.x + renderArea.width;
|
||||
|
@ -598,12 +599,19 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
|
|||
vk::Framebuffer framebuffer;
|
||||
ANGLE_VK_TRY(contextVk, framebuffer.init(contextVk->getDevice(), framebufferInfo));
|
||||
|
||||
// TODO(jmadill): Proper clear value implementation. http://anglebug.com/2361
|
||||
vk::AttachmentOpsArray renderPassAttachmentOps;
|
||||
std::vector<VkClearValue> clearValues = {{}};
|
||||
ASSERT(clearValues.size() == 1);
|
||||
|
||||
renderPassAttachmentOps.setLayout(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
renderPassAttachmentOps.setLoadOp(0, VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||
renderPassAttachmentOps.setStoreOp(0, VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_ATTACHMENT_STORE_OP_DONT_CARE);
|
||||
|
||||
ANGLE_TRY(image->beginRenderPass(contextVk, framebuffer, renderArea, renderPassDesc,
|
||||
clearValues, commandBufferOut));
|
||||
renderPassAttachmentOps, clearValues, commandBufferOut));
|
||||
|
||||
renderer->releaseObject(renderer->getCurrentQueueSerial(), &framebuffer);
|
||||
|
||||
|
|
|
@ -1081,15 +1081,40 @@ PackedAttachmentOpsDesc &AttachmentOpsArray::operator[](size_t index)
|
|||
void AttachmentOpsArray::initDummyOp(size_t index,
|
||||
VkImageLayout initialLayout,
|
||||
VkImageLayout finalLayout)
|
||||
{
|
||||
setLayout(index, initialLayout, finalLayout);
|
||||
setLoadOp(index, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
|
||||
setStoreOp(index, VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_STORE_OP_DONT_CARE);
|
||||
}
|
||||
|
||||
void AttachmentOpsArray::setLayout(size_t index,
|
||||
VkImageLayout initialLayout,
|
||||
VkImageLayout finalLayout)
|
||||
{
|
||||
PackedAttachmentOpsDesc &ops = mOps[index];
|
||||
|
||||
ops.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
ops.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
ops.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
ops.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
ops.initialLayout = static_cast<uint16_t>(initialLayout);
|
||||
ops.finalLayout = static_cast<uint16_t>(finalLayout);
|
||||
SetBitField(ops.initialLayout, initialLayout);
|
||||
SetBitField(ops.finalLayout, finalLayout);
|
||||
}
|
||||
|
||||
void AttachmentOpsArray::setLoadOp(size_t index,
|
||||
VkAttachmentLoadOp loadOp,
|
||||
VkAttachmentLoadOp stencilLoadOp)
|
||||
{
|
||||
PackedAttachmentOpsDesc &ops = mOps[index];
|
||||
|
||||
SetBitField(ops.loadOp, loadOp);
|
||||
SetBitField(ops.stencilLoadOp, stencilLoadOp);
|
||||
}
|
||||
|
||||
void AttachmentOpsArray::setStoreOp(size_t index,
|
||||
VkAttachmentStoreOp storeOp,
|
||||
VkAttachmentStoreOp stencilStoreOp)
|
||||
{
|
||||
PackedAttachmentOpsDesc &ops = mOps[index];
|
||||
|
||||
SetBitField(ops.storeOp, storeOp);
|
||||
SetBitField(ops.stencilStoreOp, stencilStoreOp);
|
||||
}
|
||||
|
||||
size_t AttachmentOpsArray::hash() const
|
||||
|
|
|
@ -116,6 +116,10 @@ class AttachmentOpsArray final
|
|||
// Initializes an attachment op with whatever values. Used for compatible RenderPass checks.
|
||||
void initDummyOp(size_t index, VkImageLayout initialLayout, VkImageLayout finalLayout);
|
||||
|
||||
void setLayout(size_t index, VkImageLayout initialLayout, VkImageLayout finalLayout);
|
||||
void setLoadOp(size_t index, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp);
|
||||
void setStoreOp(size_t index, VkAttachmentStoreOp storeOp, VkAttachmentStoreOp stencilStoreOp);
|
||||
|
||||
size_t hash() const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -267,12 +267,12 @@ TEST_P(ClearTest, ChangeFramebufferAttachmentFromRGBAtoRGB)
|
|||
GL_UNSIGNED_BYTE, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
||||
|
||||
glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
glClearColor(0.5f, 0.5f, 0.5f, 0.75f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// So far so good, we have an RGBA framebuffer that we've cleared to 0.5 everywhere.
|
||||
EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 128, 1.0);
|
||||
EXPECT_PIXEL_NEAR(0, 0, 128, 0, 128, 192, 1.0);
|
||||
|
||||
// In the Vulkan backend, RGB textures are emulated with an RGBA texture format
|
||||
// underneath and we keep a special mask to know that we shouldn't touch the alpha
|
||||
|
@ -350,7 +350,7 @@ TEST_P(ClearTest, ClearIssue)
|
|||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
|
||||
ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
|
||||
drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
|
|
|
@ -1633,6 +1633,10 @@ TEST_P(ImageTest, MipLevels)
|
|||
ANGLE_SKIP_TEST_IF(IsOzone() && IsOpenGLES());
|
||||
// Also fails on NVIDIA Shield TV bot.
|
||||
ANGLE_SKIP_TEST_IF(IsNVIDIAShield() && IsOpenGLES());
|
||||
// On Vulkan, the clear operation in the loop is optimized with a render pass loadOp=Clear. On
|
||||
// Linux/Intel, that operation is mistakenly clearing the rest of the mips to 0.
|
||||
// http://anglebug.com/3284
|
||||
ANGLE_SKIP_TEST_IF(IsVulkan() && IsLinux() && IsIntel());
|
||||
|
||||
EGLWindow *window = getEGLWindow();
|
||||
ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
|
||||
|
|
|
@ -784,6 +784,9 @@ TEST_P(MipmapTest, TextureCubeGeneralLevelZero)
|
|||
// http://anglebug.com/3145
|
||||
ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
|
||||
|
||||
// http://anglebug.com/2822
|
||||
ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
|
||||
|
||||
// Draw. Since the negative-Y face's is blue, this should be blue.
|
||||
|
@ -826,6 +829,9 @@ TEST_P(MipmapTest, TextureCubeRenderToLevelZero)
|
|||
// http://anglebug.com/3145
|
||||
ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
|
||||
|
||||
// http://anglebug.com/2822
|
||||
ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureCube);
|
||||
|
||||
// Draw. Since the negative-Y face's is blue, this should be blue.
|
||||
|
|
|
@ -93,6 +93,10 @@ TEST_P(OcclusionQueriesTest, IsNotOccluded)
|
|||
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
|
||||
!extensionEnabled("GL_EXT_occlusion_query_boolean"));
|
||||
|
||||
// TODO(syoussefi): Using render pass ops to clear the framebuffer attachment results in
|
||||
// AMD/Windows misbehaving in this test. http://anglebug.com/3286
|
||||
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
|
|
|
@ -1352,6 +1352,9 @@ TEST_P(TextureCubeTest, CubeMapFBO)
|
|||
// http://anglebug.com/3145
|
||||
ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
|
||||
|
||||
// http://anglebug.com/2822
|
||||
ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
|
||||
|
||||
GLFramebuffer fbo;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче