Commit d201ed8b by Jamie Madill Committed by Commit Bot

Vulkan: Track used Images in RenderPass.

Adding a simple ImageSerial tracking map in our RenderPass allows us to know when we do or do not need to close the RenderPass on a new Image access. This simple tracking scheme improves Manhattan performance by up to 25% on Android. The improved perf comes from reducing our RenderPass count (23->18 RenderPasses in our capture scene). Adds a FastUnorderedSet class to manage the used RP Image serials. Updates the Query helpers to explicitly flush the RP before inserting queries. Bug: angleproject:4911 Change-Id: I0c34fc8e307514ebdf3e81e08d8e5aedb70ebe8f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2334346Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 3e57e349
......@@ -474,6 +474,36 @@ class FastUnorderedMap final
FastVector<Pair, N> mData;
};
template <class T, size_t N>
class FastUnorderedSet final
{
public:
FastUnorderedSet() {}
~FastUnorderedSet() {}
bool empty() const { return mData.empty(); }
void insert(T value)
{
ASSERT(!contains(value));
mData.push_back(value);
}
bool contains(T needle) const
{
for (T value : mData)
{
if (value == needle)
return true;
}
return false;
}
void clear() { mData.clear(); }
private:
FastVector<T, N> mData;
};
} // namespace angle
#endif // COMMON_FASTVECTOR_H_
......@@ -264,4 +264,29 @@ TEST(FastUnorderedMap, BasicUsage)
EXPECT_FALSE(value);
}
}
// Basic functionality for FastUnorderedSet
TEST(FastUnorderedSet, BasicUsage)
{
FastUnorderedSet<int, 3> testMap;
EXPECT_TRUE(testMap.empty());
testMap.insert(5);
EXPECT_TRUE(testMap.contains(5));
EXPECT_FALSE(testMap.contains(6));
EXPECT_FALSE(testMap.empty());
testMap.clear();
EXPECT_TRUE(testMap.empty());
for (int i = 0; i < 10; ++i)
{
testMap.insert(i);
}
for (int i = 0; i < 10; ++i)
{
EXPECT_TRUE(testMap.contains(i));
}
}
} // namespace angle
......@@ -533,26 +533,23 @@ class ContextVk : public ContextImpl, public vk::Context
vk::ImageHelper *image)
{
ASSERT(mRenderPassCommands->started());
mRenderPassCommands->imageWrite(&mResourceUseList, aspectFlags, imageLayout, image);
mRenderPassCommands->imageWrite(&mResourceUseList, aspectFlags, imageLayout,
vk::AliasingMode::Allowed, image);
}
angle::Result getOutsideRenderPassCommandBuffer(vk::CommandBuffer **commandBufferOut)
{
// Only one command buffer should be active at a time
// TODO(jmadill): Do not end RenderPass. http://anglebug.com/4911
ASSERT(mOutsideRenderPassCommands->empty() || mRenderPassCommands->empty());
ANGLE_TRY(endRenderPass());
*commandBufferOut = &mOutsideRenderPassCommands->getCommandBuffer();
return angle::Result::Continue;
}
angle::Result flushAndBeginRenderPass(const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps,
const uint32_t depthStencilAttachmentIndex,
const vk::ClearValuesArray &clearValues,
vk::CommandBuffer **commandBufferOut);
angle::Result beginNewRenderPass(const vk::Framebuffer &framebuffer,
const gl::Rectangle &renderArea,
const vk::RenderPassDesc &renderPassDesc,
const vk::AttachmentOpsArray &renderPassAttachmentOps,
const uint32_t depthStencilAttachmentIndex,
const vk::ClearValuesArray &clearValues,
vk::CommandBuffer **commandBufferOut);
// Only returns true if we have a started RP and we've run setupDraw.
bool hasStartedRenderPass() const
......@@ -580,7 +577,7 @@ class ContextVk : public ContextImpl, public vk::Context
egl::ContextPriority getContextPriority() const override { return mContextPriority; }
angle::Result startRenderPass(gl::Rectangle renderArea, vk::CommandBuffer **commandBufferOut);
angle::Result endRenderPass();
angle::Result flushCommandsAndEndRenderPass();
angle::Result syncExternalMemory();
......@@ -910,6 +907,8 @@ class ContextVk : public ContextImpl, public vk::Context
// Pull an available CBH ptr from the CBH queue and set to specified hasRenderPass state
void getNextAvailableCommandBuffer(vk::CommandBufferHelper **commandBuffer, bool hasRenderPass);
angle::Result endRenderPassIfImageUsed(const vk::ImageHelper &image);
angle::Result endRenderPassIfTransformFeedbackBuffer(const vk::BufferHelper *buffer);
void populateTransformFeedbackBufferSet(
......@@ -1125,7 +1124,7 @@ ANGLE_INLINE angle::Result ContextVk::endRenderPassIfTransformFeedbackBuffer(
return angle::Result::Continue;
}
return endRenderPass();
return flushCommandsAndEndRenderPass();
}
ANGLE_INLINE angle::Result ContextVk::onIndexBufferChange(
......
......@@ -185,18 +185,19 @@ class FramebufferVk : public FramebufferImpl
uint8_t stencilMask,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void clearWithRenderPassOp(gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void clearWithClearAttachment(vk::CommandBuffer *renderPassCommandBuffer,
const gl::Rectangle &scissoredRenderArea,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void clearWithLoadOp(ContextVk *contextVk,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void clearWithCommand(vk::CommandBuffer *renderPassCommandBuffer,
const gl::Rectangle &scissoredRenderArea,
gl::DrawBufferMask clearColorBuffers,
bool clearDepth,
bool clearStencil,
const VkClearColorValue &clearColorValue,
const VkClearDepthStencilValue &clearDepthStencilValue);
void updateActiveColorMasks(size_t colorIndex, bool r, bool g, bool b, bool a);
void updateRenderPassDesc();
angle::Result updateColorAttachment(const gl::Context *context,
......
......@@ -986,7 +986,7 @@ void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk,
VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
commandBufferHelper->bufferWrite(resourceUseList, accessFlags,
kPipelineStageShaderMap[shaderType],
vk::BufferAliasingMode::Allowed, &bufferHelper);
vk::AliasingMode::Allowed, &bufferHelper);
}
else
{
......@@ -1056,7 +1056,7 @@ void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet(
// We set SHADER_READ_BIT to be conservative.
commandBufferHelper->bufferWrite(
resourceUseList, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
kPipelineStageShaderMap[shaderType], vk::BufferAliasingMode::Allowed, &bufferHelper);
kPipelineStageShaderMap[shaderType], vk::AliasingMode::Allowed, &bufferHelper);
writtenBindings.set(binding);
}
......
......@@ -1126,9 +1126,9 @@ angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
renderPassAttachmentOps.initWithLoadStore(0, vk::ImageLayout::ColorAttachment,
vk::ImageLayout::ColorAttachment);
ANGLE_TRY(contextVk->flushAndBeginRenderPass(
framebuffer, renderArea, renderPassDesc, renderPassAttachmentOps,
vk::kInvalidAttachmentIndex, clearValues, commandBufferOut));
ANGLE_TRY(contextVk->beginNewRenderPass(framebuffer, renderArea, renderPassDesc,
renderPassAttachmentOps, vk::kInvalidAttachmentIndex,
clearValues, commandBufferOut));
contextVk->addGarbage(&framebuffer);
......@@ -1853,7 +1853,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
descriptorPoolBinding.reset();
// Close the render pass for this temporary framebuffer.
ANGLE_TRY(contextVk->endRenderPass());
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
return angle::Result::Continue;
}
......
......@@ -1549,6 +1549,18 @@ void AttachmentOpsArray::setStencilOps(size_t index,
SetBitField(ops.stencilStoreOp, storeOp);
}
void AttachmentOpsArray::setClearOp(size_t index)
{
PackedAttachmentOpsDesc &ops = mOps[index];
SetBitField(ops.loadOp, VK_ATTACHMENT_LOAD_OP_CLEAR);
}
void AttachmentOpsArray::setClearStencilOp(size_t index)
{
PackedAttachmentOpsDesc &ops = mOps[index];
SetBitField(ops.stencilLoadOp, VK_ATTACHMENT_LOAD_OP_CLEAR);
}
size_t AttachmentOpsArray::hash() const
{
return angle::ComputeGenericHash(mOps);
......
......@@ -182,6 +182,9 @@ class AttachmentOpsArray final
void setOps(size_t index, VkAttachmentLoadOp loadOp, VkAttachmentStoreOp storeOp);
void setStencilOps(size_t index, VkAttachmentLoadOp loadOp, VkAttachmentStoreOp storeOp);
void setClearOp(size_t index);
void setClearStencilOp(size_t index);
size_t hash() const;
private:
......@@ -786,19 +789,28 @@ class PipelineHelper final : angle::NonCopyable
ANGLE_INLINE PipelineHelper::PipelineHelper(Pipeline &&pipeline) : mPipeline(std::move(pipeline)) {}
struct ImageViewSubresourceSerial
struct ImageSubresourceRange
{
ImageViewSerial imageViewSerial;
uint16_t level : 10; // GL max is 1000 (fits in 10 bits).
uint16_t levelCount : 6; // Max 63 levels (2 ** 6 - 1). If we need more, take from layer.
uint16_t layer : 15; // Implementation max is 2048 (11 bits).
uint16_t singleLayer : 1; // true/false only. Not possible to use sub-slices of levels.
};
static_assert(sizeof(ImageSubresourceRange) == sizeof(uint32_t), "Size mismatch");
constexpr ImageSubresourceRange kInvalidImageSubresourceRange = {0, 0, 0, 0};
struct ImageViewSubresourceSerial
{
ImageViewSerial imageViewSerial;
ImageSubresourceRange subresource;
};
static_assert(sizeof(ImageViewSubresourceSerial) == sizeof(uint64_t), "Size mismatch");
constexpr ImageViewSubresourceSerial kInvalidImageViewSubresourceSerial = {kInvalidImageViewSerial,
0, 0, 0, 0};
constexpr ImageViewSubresourceSerial kInvalidImageViewSubresourceSerial = {
kInvalidImageViewSerial, kInvalidImageSubresourceRange};
class TextureDescriptorDesc
{
......
......@@ -604,7 +604,7 @@ void CommandBufferHelper::bufferRead(ResourceUseList *resourceUseList,
void CommandBufferHelper::bufferWrite(ResourceUseList *resourceUseList,
VkAccessFlags writeAccessType,
PipelineStage writeStage,
BufferAliasingMode aliasingMode,
AliasingMode aliasingMode,
BufferHelper *buffer)
{
buffer->retain(resourceUseList);
......@@ -618,7 +618,7 @@ void CommandBufferHelper::bufferWrite(ResourceUseList *resourceUseList,
// We support aliasing by not tracking storage buffers. This works well with the GL API
// because storage buffers are required to be externally synchronized.
// Compute / XFB emulation buffers are not allowed to alias.
if (aliasingMode == BufferAliasingMode::Disallowed)
if (aliasingMode == AliasingMode::Disallowed)
{
ASSERT(!usesBuffer(*buffer));
mUsedBuffers.insert(buffer->getBufferSerial(), BufferAccess::Write);
......@@ -641,11 +641,22 @@ void CommandBufferHelper::imageRead(ResourceUseList *resourceUseList,
mPipelineBarrierMask.set(barrierIndex);
}
}
if (mIsRenderPassCommandBuffer)
{
// As noted in the header we don't support multiple layouts reads for Images.
// We allow duplicate uses in the RP to accomodate for normal GL sampler usage.
if (!usesImageInRenderPass(*image))
{
mRenderPassUsedImages.insert(image->getImageSerial());
}
}
}
void CommandBufferHelper::imageWrite(ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
ImageLayout imageLayout,
AliasingMode aliasingMode,
ImageHelper *image)
{
image->retain(resourceUseList);
......@@ -658,6 +669,19 @@ void CommandBufferHelper::imageWrite(ResourceUseList *resourceUseList,
{
mPipelineBarrierMask.set(barrierIndex);
}
if (mIsRenderPassCommandBuffer)
{
// When used as a storage buffer we allow for aliased writes.
if (aliasingMode == AliasingMode::Disallowed)
{
ASSERT(!usesImageInRenderPass(*image));
}
if (!usesImageInRenderPass(*image))
{
mRenderPassUsedImages.insert(image->getImageSerial());
}
}
}
void CommandBufferHelper::executeBarriers(PrimaryCommandBuffer *primary)
......@@ -928,11 +952,13 @@ void CommandBufferHelper::reset()
mDepthTestEverEnabled = false;
mStencilTestEverEnabled = false;
mDepthStencilAttachmentIndex = kInvalidAttachmentIndex;
mRenderPassUsedImages.clear();
}
// This state should never change for non-renderPass command buffer
ASSERT(mRenderPassStarted == false);
ASSERT(mValidTransformFeedbackBufferCount == 0);
ASSERT(mRebindTransformFeedbackBuffers == false);
ASSERT(mRenderPassUsedImages.empty());
}
void CommandBufferHelper::releaseToContextQueue(ContextVk *contextVk)
......@@ -969,6 +995,35 @@ void CommandBufferHelper::pauseTransformFeedbackIfStarted()
mTransformFeedbackCounterBuffers.data());
}
void CommandBufferHelper::updateRenderPassColorClear(size_t colorIndex,
const VkClearValue &clearValue)
{
mAttachmentOps.setClearOp(colorIndex);
mClearValues.store(static_cast<uint32_t>(colorIndex), VK_IMAGE_ASPECT_COLOR_BIT, clearValue);
}
void CommandBufferHelper::updateRenderPassDepthStencilClear(VkImageAspectFlags aspectFlags,
const VkClearValue &clearValue)
{
// Don't overwrite prior clear values for individual aspects.
VkClearValue combinedClearValue = mClearValues[mDepthStencilAttachmentIndex];
if ((aspectFlags & VK_IMAGE_ASPECT_DEPTH_BIT) != 0)
{
mAttachmentOps.setClearOp(mDepthStencilAttachmentIndex);
combinedClearValue.depthStencil.depth = clearValue.depthStencil.depth;
}
if ((aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT) != 0)
{
mAttachmentOps.setClearStencilOp(mDepthStencilAttachmentIndex);
combinedClearValue.depthStencil.stencil = clearValue.depthStencil.stencil;
}
// Bypass special D/S handling. This clear values array stores values packed.
mClearValues.storeNoDepthStencil(mDepthStencilAttachmentIndex, combinedClearValue);
}
// DynamicBuffer implementation.
DynamicBuffer::DynamicBuffer()
: mUsage(0),
......@@ -1766,6 +1821,11 @@ void QueryHelper::resetQueryPool(ContextVk *contextVk,
angle::Result QueryHelper::beginQuery(ContextVk *contextVk)
{
if (contextVk->hasStartedRenderPass())
{
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
}
CommandBuffer *outsideRenderPassCommandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&outsideRenderPassCommandBuffer));
const QueryPool &queryPool = getQueryPool();
......@@ -1777,6 +1837,11 @@ angle::Result QueryHelper::beginQuery(ContextVk *contextVk)
angle::Result QueryHelper::endQuery(ContextVk *contextVk)
{
if (contextVk->hasStartedRenderPass())
{
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
}
CommandBuffer *outsideRenderPassCommandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&outsideRenderPassCommandBuffer));
outsideRenderPassCommandBuffer->endQuery(getQueryPool().getHandle(), mQuery);
......@@ -1800,14 +1865,21 @@ void QueryHelper::endOcclusionQuery(ContextVk *contextVk, CommandBuffer *renderP
angle::Result QueryHelper::flushAndWriteTimestamp(ContextVk *contextVk)
{
if (contextVk->hasStartedRenderPass())
{
ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
}
CommandBuffer *outsideRenderPassCommandBuffer;
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&outsideRenderPassCommandBuffer));
writeTimestamp(contextVk, outsideRenderPassCommandBuffer);
return angle::Result::Continue;
}
void QueryHelper::writeTimestamp(ContextVk *contextVk, PrimaryCommandBuffer *primary)
void QueryHelper::writeTimestampToPrimary(ContextVk *contextVk, PrimaryCommandBuffer *primary)
{
// Note that commands may not be flushed at this point.
const QueryPool &queryPool = getQueryPool();
primary->resetQueryPool(queryPool, mQuery, 1);
primary->writeTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool, mQuery);
......@@ -4550,11 +4622,6 @@ angle::Result ImageHelper::copyImageDataToBuffer(ContextVk *contextVk,
ANGLE_TRY(allocateStagingMemory(contextVk, *bufferSize, outDataPtr, bufferOut, bufferOffsetsOut,
nullptr));
CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(contextVk->onImageTransferRead(aspectFlags, this));
ANGLE_TRY(contextVk->onBufferTransferWrite(*bufferOut));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
uint32_t sourceLevelVk = static_cast<uint32_t>(sourceLevelGL) - mBaseLevel;
VkBufferImageCopy regions[2] = {};
......@@ -4603,10 +4670,14 @@ angle::Result ImageHelper::copyImageDataToBuffer(ContextVk *contextVk,
regions[1].imageSubresource.baseArrayLayer = baseLayer;
regions[1].imageSubresource.layerCount = layerCount;
regions[1].imageSubresource.mipLevel = sourceLevelVk;
commandBuffer->copyImageToBuffer(mImage, getCurrentLayout(),
(*bufferOut)->getBuffer().getHandle(), 1, &regions[1]);
}
CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(contextVk->onBufferTransferWrite(*bufferOut));
ANGLE_TRY(contextVk->onImageTransferRead(aspectFlags, this));
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(&commandBuffer));
commandBuffer->copyImageToBuffer(mImage, getCurrentLayout(),
(*bufferOut)->getBuffer().getHandle(), 1, regions);
......@@ -5365,10 +5436,10 @@ ImageViewSubresourceSerial ImageViewHelper::getSubresourceSerial(uint32_t levelG
ImageViewSubresourceSerial serial;
serial.imageViewSerial = mImageViewSerial;
SetBitField(serial.level, levelGL);
SetBitField(serial.levelCount, levelCount);
SetBitField(serial.layer, layer);
SetBitField(serial.singleLayer, layerMode == LayerMode::Single ? 1 : 0);
SetBitField(serial.subresource.level, levelGL);
SetBitField(serial.subresource.levelCount, levelCount);
SetBitField(serial.subresource.layer, layer);
SetBitField(serial.subresource.singleLayer, layerMode == LayerMode::Single ? 1 : 0);
return serial;
}
......
......@@ -422,7 +422,7 @@ class QueryHelper final
angle::Result flushAndWriteTimestamp(ContextVk *contextVk);
// When syncing gpu/cpu time, main thread accesses primary directly
void writeTimestamp(ContextVk *contextVk, PrimaryCommandBuffer *primary);
void writeTimestampToPrimary(ContextVk *contextVk, PrimaryCommandBuffer *primary);
// All other timestamp accesses should be made on outsideRenderPassCommandBuffer
void writeTimestamp(ContextVk *contextVk, CommandBuffer *outsideRenderPassCommandBuffer);
......@@ -837,7 +837,7 @@ enum class BufferAccess
Write,
};
enum class BufferAliasingMode
enum class AliasingMode
{
Allowed,
Disallowed,
......@@ -851,7 +851,7 @@ enum class BufferAliasingMode
// into the CBH and then pass the CBH off to a worker thread that will
// process the commands into a primary command buffer and then submit
// those commands to the queue.
struct CommandBufferHelper : angle::NonCopyable
class CommandBufferHelper : angle::NonCopyable
{
public:
CommandBufferHelper();
......@@ -867,17 +867,17 @@ struct CommandBufferHelper : angle::NonCopyable
void bufferWrite(ResourceUseList *resourceUseList,
VkAccessFlags writeAccessType,
PipelineStage writeStage,
BufferAliasingMode aliasingMode,
AliasingMode aliasingMode,
BufferHelper *buffer);
void imageRead(ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
ImageLayout imageLayout,
ImageHelper *image);
void imageWrite(ResourceUseList *resourceUseList,
VkImageAspectFlags aspectFlags,
ImageLayout imageLayout,
AliasingMode aliasingMode,
ImageHelper *image);
CommandBuffer &getCommandBuffer() { return mCommandBuffer; }
......@@ -946,6 +946,10 @@ struct CommandBufferHelper : angle::NonCopyable
SetBitField(mAttachmentOps[attachmentIndex].finalLayout, finalLayout);
}
void updateRenderPassColorClear(size_t colorIndex, const VkClearValue &colorClearValue);
void updateRenderPassDepthStencilClear(VkImageAspectFlags aspectFlags,
const VkClearValue &clearValue);
const gl::Rectangle &getRenderArea() const
{
ASSERT(mIsRenderPassCommandBuffer);
......@@ -971,6 +975,7 @@ struct CommandBufferHelper : angle::NonCopyable
bool usesBuffer(const BufferHelper &buffer) const;
bool usesBufferForWrite(const BufferHelper &buffer) const;
bool usesImageInRenderPass(const ImageHelper &image) const;
// Dumping the command stream is disabled by default.
static constexpr bool kEnableCommandStreamDiagnostics = false;
......@@ -1011,8 +1016,11 @@ struct CommandBufferHelper : angle::NonCopyable
uint32_t mDepthStencilAttachmentIndex;
// Tracks resources used in the command buffer.
static constexpr uint32_t kFastMapSize = 8;
// For Buffers, we track the read/write access type so we can enable simuntaneous reads.
// Images have unique layouts unlike buffers therefore we don't support multi-read.
static constexpr uint32_t kFastMapSize = 16;
angle::FastUnorderedMap<BufferSerial, BufferAccess, kFastMapSize> mUsedBuffers;
angle::FastUnorderedSet<ImageSerial, kFastMapSize> mRenderPassUsedImages;
};
static constexpr uint32_t kInvalidAttachmentIndex = -1;
......@@ -1963,6 +1971,12 @@ class ActiveHandleCounter final : angle::NonCopyable
angle::PackedEnumMap<HandleType, uint32_t> mActiveCounts;
angle::PackedEnumMap<HandleType, uint32_t> mAllocatedCounts;
};
ANGLE_INLINE bool CommandBufferHelper::usesImageInRenderPass(const ImageHelper &image) const
{
ASSERT(mIsRenderPassCommandBuffer);
return mRenderPassUsedImages.contains(image.getImageSerial());
}
} // namespace vk
} // namespace rx
......
......@@ -741,17 +741,22 @@ void ClearValuesArray::store(uint32_t index,
// Ensure for packed DS we're writing to the depth index.
ASSERT(index == kClearValueDepthIndex ||
(index == kClearValueStencilIndex && aspectFlags == VK_IMAGE_ASPECT_STENCIL_BIT));
mValues[kClearValueStencilIndex] = clearValue;
mEnabled.set(kClearValueStencilIndex);
storeNoDepthStencil(kClearValueStencilIndex, clearValue);
}
if (aspectFlags != VK_IMAGE_ASPECT_STENCIL_BIT)
{
mValues[index] = clearValue;
mEnabled.set(index);
storeNoDepthStencil(index, clearValue);
}
}
void ClearValuesArray::storeNoDepthStencil(uint32_t index, const VkClearValue &clearValue)
{
mValues[index] = clearValue;
mEnabled.set(index);
}
// ResourceSerialFactory implementation.
ResourceSerialFactory::ResourceSerialFactory() : mCurrentUniqueSerial(1) {}
......
......@@ -659,6 +659,7 @@ class ClearValuesArray final
ClearValuesArray &operator=(const ClearValuesArray &rhs);
void store(uint32_t index, VkImageAspectFlags aspectFlags, const VkClearValue &clearValue);
void storeNoDepthStencil(uint32_t index, const VkClearValue &clearValue);
void reset(size_t index)
{
......
......@@ -1382,7 +1382,7 @@ TEST_P(VertexAttributeTest, DisabledAttribArrays)
drawQuad(program, "a_position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << "color index " << colorIndex;
glDeleteProgram(program);
}
......
......@@ -39,9 +39,6 @@ class VulkanPerformanceCounterTest : public ANGLETest
// Tests that texture updates to unused textures don't break the RP.
TEST_P(VulkanPerformanceCounterTest, NewTextureDoesNotBreakRenderPass)
{
// TODO(jmadill): Fix test. http://anglebug.com/4911
ANGLE_SKIP_TEST_IF(IsVulkan());
const rx::vk::PerfCounters &counters = hackANGLE();
GLColor kInitialData[4] = {GLColor::red, GLColor::blue, GLColor::green, GLColor::yellow};
......
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