Vulkan: Add feature avoid HOST_VISIBLE and DEVICE_LOCAL combination

Discrete GPUs device local memory usually is not CPU accessible. This
adds a feature flag to control that.

Fixed bug in BufferVk that when mapRangeImpl is called from angle
internal, unmapImpl was using front end mapping parameters that is
incorrect. We have to cache the mapping parameters in the backend to
hangle the mapRangeImpl/unmapImpl calls from internal.

Fixed the test bug in ComputeShaderTest.BufferImageBufferMapWrite that
we are calling glMapBufferRange with GL_MAP_READ_BIT but are actually
writing to the map pointer. This should result in undefined behavior per
spec.

Fixed the test bug in GLSLTest.* that VerifyBuffer calls
glMapBufferRange, but was giving incorrect length which result in data
only been partially copied. This bug was hidden due to previously all
buffers are CPU accessible and there is no copy needed.

Fixed the test bug in ReadPixelsPBOTest.* and ReadPixelsPBONVTest.* that
calls glMapBufferRangeEXT, but was giving incorrect length which result
in data only been partially copied. This bug was hidden due to
previously all buffers are CPU accessible and there is no copy needed.

Added new skipped syncval messages. Because this CL triggers a
copyToBuffer call for some of the buffers and that changes the syncval
message signature for the same reasons (i.e, feedback loop or synval
does not know the exact range of buffer been used for vertex buffers
etc).

Bug: angleproject:7047
Change-Id: I28c96ae0f23db8e5b51af8259e5b97e12e8b91f2
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3597711
Reviewed-by: Yuxin Hu <yuxinhu@google.com>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Commit-Queue: Charlie Lao <cclao@google.com>
This commit is contained in:
Charlie Lao 2022-04-20 10:44:24 -07:00 коммит произвёл Angle LUCI CQ
Родитель d988db39b0
Коммит 3b38b37907
13 изменённых файлов: 144 добавлений и 46 удалений

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

@ -593,6 +593,11 @@ struct FeaturesVk : FeatureSetBase
"createPipelineDuringLink", FeatureCategory::VulkanFeatures,
"Create pipeline with default state during glLinkProgram", &members,
"http://anglebug.com/7046"};
FeatureInfo preferDeviceLocalMemoryHostVisible = {
"preferDeviceLocalMemoryHostVisible", FeatureCategory::VulkanFeatures,
"Prefer adding HOST_VISIBLE flag for DEVICE_LOCAL memory when picking memory types",
&members, "http://anglebug.com/7047"};
};
inline FeaturesVk::FeaturesVk() = default;

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

@ -887,6 +887,15 @@
"Create pipeline with default state during glLinkProgram"
],
"issue": "http://anglebug.com/7046"
},
{
"name": "prefer_device_local_memory_host_visible",
"category": "Features",
"description": [
"Prefer adding HOST_VISIBLE flag for DEVICE_LOCAL memory when picking memory types"
],
"issue": "http://anglebug.com/7047"
}
]
}

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

@ -6,7 +6,7 @@
"include/platform/FeaturesMtl.h":
"84ab0985624641c8b3894c3ab08820cf",
"include/platform/FeaturesVk.h":
"52c0687135636d701cf7c43f6358e9c4",
"661db47ce5ed8637f851b14c02551bf5",
"include/platform/FrontendFeatures.h":
"ee4c60a2388ec39b3a63488a3f42282c",
"include/platform/d3d_features.json":
@ -20,9 +20,9 @@
"include/platform/mtl_features.json":
"9ff73684f28ff8df40fb66da8fe4713a",
"include/platform/vk_features.json":
"80d2fa526bd59fcb6df368cc3b5f510d",
"2e03e03fc76946ac7bd96127e8dc0012",
"util/angle_features_autogen.cpp":
"79f67c452a945a5515d16ac80035f00c",
"094764c9b5156a25e5982c17ec2fc7ef",
"util/angle_features_autogen.h":
"337975ddfeed8355d04983f41067f0ec"
"7c80b9df0a147c7cb05f1a46dd1efd47"
}

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

@ -54,10 +54,12 @@ constexpr size_t kConvertedArrayBufferInitialSize = 1024 * 8;
// device local memory to speed up access to and from the GPU.
// Dynamic usage patterns or that are frequently mapped
// will now request host cached memory to speed up access from the CPU.
ANGLE_INLINE VkMemoryPropertyFlags GetPreferredMemoryType(gl::BufferBinding target,
ANGLE_INLINE VkMemoryPropertyFlags GetPreferredMemoryType(RendererVk *renderer,
gl::BufferBinding target,
gl::BufferUsage usage)
{
constexpr VkMemoryPropertyFlags kDeviceLocalFlags =
constexpr VkMemoryPropertyFlags kDeviceLocalFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
constexpr VkMemoryPropertyFlags kDeviceLocalHostVisibleFlags =
(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
constexpr VkMemoryPropertyFlags kHostCachedFlags =
@ -77,7 +79,9 @@ ANGLE_INLINE VkMemoryPropertyFlags GetPreferredMemoryType(gl::BufferBinding targ
case gl::BufferUsage::StaticDraw:
case gl::BufferUsage::StaticRead:
// For static usage, request a device local memory
return kDeviceLocalFlags;
return renderer->getFeatures().preferDeviceLocalMemoryHostVisible.enabled
? kDeviceLocalHostVisibleFlags
: kDeviceLocalFlags;
case gl::BufferUsage::DynamicDraw:
case gl::BufferUsage::StreamDraw:
// For non-static usage where the CPU performs a write-only access, request
@ -95,15 +99,25 @@ ANGLE_INLINE VkMemoryPropertyFlags GetPreferredMemoryType(gl::BufferBinding targ
}
}
ANGLE_INLINE VkMemoryPropertyFlags GetStorageMemoryType(GLbitfield storageFlags,
ANGLE_INLINE VkMemoryPropertyFlags GetStorageMemoryType(RendererVk *renderer,
GLbitfield storageFlags,
bool externalBuffer)
{
constexpr VkMemoryPropertyFlags kDeviceLocalFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
constexpr VkMemoryPropertyFlags kDeviceLocalHostVisibleFlags =
(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
constexpr VkMemoryPropertyFlags kDeviceLocalHostCoherentFlags =
(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
const bool hasMapAccess = (storageFlags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) != 0;
if (!renderer->getFeatures().preferDeviceLocalMemoryHostVisible.enabled && !hasMapAccess)
{
// Don't use host visible bit if buffer is not going to be accessed via map and feature bits
// also don't prefer.
return kDeviceLocalFlags;
}
const bool isCoherentMap = (storageFlags & GL_MAP_COHERENT_BIT_EXT) != 0;
const bool isPersistentMap = (storageFlags & GL_MAP_PERSISTENT_BIT_EXT) != 0;
@ -231,7 +245,10 @@ BufferVk::BufferVk(const gl::BufferState &state)
mMemoryTypeIndex(0),
mMemoryPropertyFlags(0),
mIsStagingBufferMapped(false),
mHasValidData(false)
mHasValidData(false),
mIsMappedForWrite(false),
mMappedOffset(0),
mMappedLength(0)
{}
BufferVk::~BufferVk() {}
@ -293,6 +310,7 @@ angle::Result BufferVk::setDataWithUsageFlags(const gl::Context *context,
gl::BufferUsage usage,
GLbitfield flags)
{
ContextVk *contextVk = vk::GetImpl(context);
VkMemoryPropertyFlags memoryPropertyFlags = 0;
bool persistentMapRequired = false;
const bool isExternalBuffer = clientBuffer != nullptr;
@ -302,14 +320,15 @@ angle::Result BufferVk::setDataWithUsageFlags(const gl::Context *context,
case gl::BufferUsage::InvalidEnum:
{
// glBufferStorage API call
memoryPropertyFlags = GetStorageMemoryType(flags, isExternalBuffer);
memoryPropertyFlags =
GetStorageMemoryType(contextVk->getRenderer(), flags, isExternalBuffer);
persistentMapRequired = (flags & GL_MAP_PERSISTENT_BIT_EXT) != 0;
break;
}
default:
{
// glBufferData API call
memoryPropertyFlags = GetPreferredMemoryType(target, usage);
memoryPropertyFlags = GetPreferredMemoryType(contextVk->getRenderer(), target, usage);
break;
}
}
@ -321,8 +340,7 @@ angle::Result BufferVk::setDataWithUsageFlags(const gl::Context *context,
{
// If external buffer's memory does not support host visible memory property, we cannot
// support a persistent map request.
ANGLE_VK_CHECK(vk::GetImpl(context), !persistentMapRequired,
VK_ERROR_MEMORY_MAP_FAILED);
ANGLE_VK_CHECK(contextVk, !persistentMapRequired, VK_ERROR_MEMORY_MAP_FAILED);
}
mClientBuffer = clientBuffer;
@ -339,8 +357,10 @@ angle::Result BufferVk::setData(const gl::Context *context,
size_t size,
gl::BufferUsage usage)
{
ContextVk *contextVk = vk::GetImpl(context);
// Assume host visible/coherent memory available.
VkMemoryPropertyFlags memoryPropertyFlags = GetPreferredMemoryType(target, usage);
VkMemoryPropertyFlags memoryPropertyFlags =
GetPreferredMemoryType(contextVk->getRenderer(), target, usage);
return setDataWithMemoryType(context, target, data, size, memoryPropertyFlags, false, usage);
}
@ -602,10 +622,15 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk,
GLbitfield access,
void **mapPtr)
{
uint8_t **mapPtrBytes = reinterpret_cast<uint8_t **>(mapPtr);
ASSERT(mBuffer.valid());
// Record map call parameters in case this call is from angle internal (the access/offset/length
// will be inconsistent from mState).
mIsMappedForWrite = (access & GL_MAP_WRITE_BIT) != 0;
mMappedOffset = offset;
mMappedLength = length;
uint8_t **mapPtrBytes = reinterpret_cast<uint8_t **>(mapPtr);
bool hostVisible = mBuffer.isHostVisible();
// MAP_UNSYNCHRONIZED_BIT, so immediately map.
@ -707,15 +732,13 @@ angle::Result BufferVk::unmapImpl(ContextVk *contextVk)
{
ASSERT(mBuffer.valid());
bool writeOperation = ((mState.getAccessFlags() & GL_MAP_WRITE_BIT) != 0);
if (mIsStagingBufferMapped)
{
ASSERT(mStagingBuffer.valid());
// The buffer is device local or optimization of small range map.
if (writeOperation)
if (mIsMappedForWrite)
{
ANGLE_TRY(flushStagingBuffer(contextVk, mState.getMapOffset(), mState.getMapLength()));
ANGLE_TRY(flushStagingBuffer(contextVk, mMappedOffset, mMappedLength));
}
mIsStagingBufferMapped = false;
@ -726,11 +749,16 @@ angle::Result BufferVk::unmapImpl(ContextVk *contextVk)
mBuffer.unmap(contextVk->getRenderer());
}
if (writeOperation)
if (mIsMappedForWrite)
{
dataUpdated();
}
// Reset the mapping parameters
mIsMappedForWrite = false;
mMappedOffset = 0;
mMappedLength = 0;
return angle::Result::Continue;
}
@ -839,6 +867,8 @@ angle::Result BufferVk::acquireAndUpdate(ContextVk *contextVk,
{
// We shouldn't get here if this is external memory
ASSERT(!isExternalBuffer());
// If StorageRedefined, we can not use mState.getSize() to allocate a new buffer.
ASSERT(updateType != BufferUpdateType::StorageRedefined);
// Here we acquire a new BufferHelper and directUpdate() the new buffer.
// If the subData size was less than the buffer's size we additionally enqueue
@ -934,11 +964,18 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk,
// else update the buffer directly
if (isCurrentlyInUse(contextVk))
{
// If storage has just been redefined, don't go down acquireAndUpdate code path. There is no
// reason you acquire another new buffer right after redefined. And if we do go into
// acquireAndUpdate, you will also run int correctness bug that mState.getSize() has not
// been updated with new size and you will acquire a new buffer with wrong size. This could
// happen if the buffer memory is DEVICE_LOCAL and
// renderer->getFeatures().allocateNonZeroMemory.enabled is true. In this case we will issue
// a copyToBuffer immediately after allocation and isCurrentlyInUse will be true.
// If BufferVk does not have any valid data, which means there is no data needs to be copied
// from old buffer to new buffer when we acquire a new buffer, we also favor
// acquireAndUpdate over stagedUpdate. This could happen when app calls glBufferData with
// same size and we will try to reuse the existing buffer storage.
if (!isExternalBuffer() &&
if (!isExternalBuffer() && updateType != BufferUpdateType::StorageRedefined &&
(!mHasValidData || ShouldAllocateNewMemoryForUpdate(
contextVk, size, static_cast<size_t>(mState.getSize()))))
{

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

@ -217,6 +217,16 @@ class BufferVk : public BufferImpl
// Tracks if BufferVk object has valid data or not.
bool mHasValidData;
// True if the buffer is currently mapped for CPU write access. If the map call is originated
// from OpenGLES API call, then this should be consistent with mState.getAccessFlags() bits.
// Otherwise it is mapped from ANGLE internal and will not be consistent with mState access
// bits, so we have to keep record of it.
bool mIsMappedForWrite;
// Similar as mIsMappedForWrite, this maybe different from mState's getMapOffset/getMapLength if
// mapped from angle internal.
VkDeviceSize mMappedOffset;
VkDeviceSize mMappedLength;
};
} // namespace rx

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

@ -344,14 +344,7 @@ constexpr SkippedSyncvalMessage kSkippedSyncvalMessages[] = {
"type: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageLayout: VK_IMAGE_LAYOUT_GENERAL, "
"binding #0, index 0. Access info (usage: SYNC_FRAGMENT_SHADER_SHADER_STORAGE_READ, "
"prior_usage: SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, write_barriers: 0, "
"command: vkCmdDraw, seq_no: 6",
},
{
"SYNC-HAZARD-READ_AFTER_WRITE",
"type: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageLayout: VK_IMAGE_LAYOUT_GENERAL, "
"binding #0, index 0. Access info (usage: SYNC_FRAGMENT_SHADER_SHADER_STORAGE_READ, "
"prior_usage: SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, write_barriers: 0, "
"command: vkCmdDraw, seq_no: 7",
"command: vkCmdDraw",
},
// From: FramebufferTest_ES3.FramebufferBindToNewLevelAfterMaxIncreaseShouldntCrash/ES3_Vulkan
{
@ -481,6 +474,12 @@ constexpr SkippedSyncvalMessage kSkippedSyncvalMessages[] = {
"Access info (usage: SYNC_COPY_TRANSFER_WRITE, prior_usage: "
"SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ",
},
{
"SYNC-HAZARD-WRITE_AFTER_READ",
"vkCmdCopyBuffer: Hazard WRITE_AFTER_READ for dstBuffer VkBuffer",
"Access info (usage: SYNC_COPY_TRANSFER_WRITE, prior_usage: "
"SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ",
},
{
"SYNC-HAZARD-WRITE_AFTER_READ",
"vkCmdDispatch: Hazard WRITE_AFTER_READ for VkBuffer",
@ -2886,6 +2885,9 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
const bool isImmediateModeRenderer = isNvidia || isAMD || isIntel || isSamsung || isSwiftShader;
const bool isTileBasedRenderer = isARM || isPowerVR || isQualcomm || isBroadcom;
bool isDiscreteGPU =
mPhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
// Make sure all known architectures are accounted for.
if (!isImmediateModeRenderer && !isTileBasedRenderer && !isMockICDEnabled())
{
@ -3336,6 +3338,10 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
ANGLE_FEATURE_CONDITION(&mFeatures, generateSPIRVThroughGlslang, kUseSpirvGenThroughGlslang);
// For discrete GPUs, most of device local memory is host invisible. We should not force the
// host visible flag for them and result in allocation failure.
ANGLE_FEATURE_CONDITION(&mFeatures, preferDeviceLocalMemoryHostVisible, !isDiscreteGPU);
ApplyFeatureOverrides(&mFeatures, displayVk->getState());
// Disable async command queue when using Vulkan secondary command buffers temporarily to avoid

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

@ -499,9 +499,24 @@
1224996 WIN AMD VULKAN : GLSLTest_ES3.InitGlobalComplexConstant/* = SKIP
1224996 WIN AMD VULKAN : GLSLTest_ES31.TypesUsedInDifferentBlockStorages/* = SKIP
7144 WIN AMD VULKAN : GLSLTest.AliasingFunctionOutParamAndGlobal/* = SKIP
// Test is disabled as it only pertains to desktop GLSL
6197 : GLSLTest_ES31.InterpolateAtWithSwizzle/* = SKIP
// The following tests are disabled because of AMD vulkan driver crash on compiling compute shader for convertIndexBufferGPU
7227 WIN AMD VULKAN : DrawElementsTest.PartOfIndexBufferThenAll/* = SKIP
7227 WIN AMD VULKAN : GLSLTest_ES3.GLVertexIDIntegerTextureDrawElementsU8/* = SKIP
7227 WIN AMD VULKAN : IndexedPointsTestUByte.* = SKIP
7227 WIN AMD VULKAN : InstancingTest.IndexedAttrib0TriFanBuffer* = SKIP
7227 WIN AMD VULKAN : InstancingTest.IndexedAttrib1TriFanBuffer* = SKIP
7227 WIN AMD VULKAN : MultisampleTest.ContentPresevedAfterInterruption/* = SKIP
7227 WIN AMD VULKAN : RobustResourceInitTest.OutOfBoundsIndexBuffers/* = SKIP
7227 WIN AMD VULKAN : SimpleStateChangeTest.DrawElementsThenDrawElementsNewIndexBuffer/* = SKIP
7227 WIN AMD VULKAN : SimpleStateChangeTest.DrawElementsUBYTEX2ThenDrawElementsUSHORT/* = SKIP
7227 WIN AMD VULKAN : SimpleStateChangeTest.UpdateBoundElementArrayBuffer/* = SKIP
7227 WIN AMD VULKAN : TriangleFanDrawTest.DrawTriangleFanElements/* = SKIP
7227 WIN AMD VULKAN : TriangleFanDrawTest.DrawTriangleFanPrimitiveRestartAt* = SKIP
7227 WIN AMD VULKAN : WebGLCompatibilityTest.DrawElementsBufferOutOfBoundsInIndexBuffer/* = SKIP
7227 WIN AMD VULKAN : WebGLCompatibilityTest.DrawElementsBufferOutOfBoundsInVertexBuffer/* = SKIP
7227 WIN AMD VULKAN : WebGLCompatibilityTest.DrawElementsOffsetRestriction/* = SKIP
// Slow tests
5076 : GLSLTest.VerifyMaxVertexUniformVectors* = TIMEOUT

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

@ -523,7 +523,7 @@ void main()
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
mappedBuffer =
glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_WRITE_BIT);
memcpy(mappedBuffer, expectedBufferData, sizeof(expectedBufferData));
glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);

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

@ -9659,12 +9659,16 @@ void InitBuffer(GLuint program,
template <typename T>
bool VerifyBuffer(GLuint buffer, const T data[], uint32_t dataSize)
{
uint32_t sizeInBytes = dataSize * sizeof(*data);
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
const T *ptr = reinterpret_cast<const T *>(
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, dataSize, GL_MAP_READ_BIT));
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeInBytes, GL_MAP_READ_BIT));
bool isCorrect = memcmp(ptr, data, dataSize * sizeof(*data)) == 0;
bool isCorrect = memcmp(ptr, data, sizeInBytes) == 0;
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
return isCorrect;

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

@ -79,8 +79,9 @@ class ReadPixelsPBONVTest : public ReadPixelsTest
{
ANGLE_SKIP_TEST_IF(!hasPBOExts());
mPBOBufferSize = bufferSize;
glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
glBufferData(GL_PIXEL_PACK_BUFFER, mPBOBufferSize, nullptr, GL_STATIC_DRAW);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glDeleteTextures(1, &mTexture);
@ -115,6 +116,7 @@ class ReadPixelsPBONVTest : public ReadPixelsTest
GLuint mFBO = 0;
GLuint mFBOWidth = 0;
GLuint mFBOHeight = 0;
GLuint mPBOBufferSize = 0;
};
// Test basic usage of PBOs.
@ -140,7 +142,7 @@ TEST_P(ReadPixelsPBONVTest, Basic)
glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
void *mappedPtr = glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
void *mappedPtr = glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER, 0, mPBOBufferSize, GL_MAP_READ_BIT);
GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
EXPECT_GL_NO_ERROR();

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

@ -774,19 +774,27 @@ TEST_P(VulkanPerformanceCounterTest, IndependentBufferCopiesShareSingleBarrier)
// Step 1: Set up four buffers for two copies.
GLBuffer srcA;
glBindBuffer(GL_COPY_READ_BUFFER, srcA);
glBufferData(GL_COPY_READ_BUFFER, sizeof(srcDataA), srcDataA, GL_STATIC_COPY);
// Note: We can't use GL_STATIC_COPY. Using STATIC will cause driver to allocate a host
// invisible memory and issue a copyToBuffer, which will trigger outsideRenderPassCommandBuffer
// flush when glCopyBufferSubData is called due to read after write. That will break the
// expectations and cause test to fail.
glBufferData(GL_COPY_READ_BUFFER, sizeof(srcDataA), srcDataA, GL_DYNAMIC_COPY);
GLBuffer dstA;
glBindBuffer(GL_COPY_WRITE_BUFFER, dstA);
glBufferData(GL_COPY_WRITE_BUFFER, sizeof(srcDataA[0]) * 2, nullptr, GL_STATIC_COPY);
// Note: We can't use GL_STATIC_COPY. Using STATIC will cause driver to allocate a host
// invisible memory and issue a copyToBuffer, which will trigger outsideRenderPassCommandBuffer
// flush when glCopyBufferSubData is called due to write after write. That will break the
// expectations and cause test to fail.
glBufferData(GL_COPY_WRITE_BUFFER, sizeof(srcDataA[0]) * 2, nullptr, GL_DYNAMIC_COPY);
GLBuffer srcB;
glBindBuffer(GL_COPY_READ_BUFFER, srcB);
glBufferData(GL_COPY_READ_BUFFER, sizeof(srcDataB), srcDataB, GL_STATIC_COPY);
glBufferData(GL_COPY_READ_BUFFER, sizeof(srcDataB), srcDataB, GL_DYNAMIC_COPY);
GLBuffer dstB;
glBindBuffer(GL_COPY_WRITE_BUFFER, dstB);
glBufferData(GL_COPY_WRITE_BUFFER, sizeof(srcDataB[0]) * 2, nullptr, GL_STATIC_COPY);
glBufferData(GL_COPY_WRITE_BUFFER, sizeof(srcDataB[0]) * 2, nullptr, GL_DYNAMIC_COPY);
// We expect that ANGLE generate zero additional command buffers.
uint32_t expectedFlushCount = getPerfCounters().flushedOutsideRenderPassCommandBuffers;

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

@ -167,6 +167,7 @@ constexpr PackedEnumMap<Feature, const char *> kFeatureNames = {{
{Feature::PreAddTexelFetchOffsets, "preAddTexelFetchOffsets"},
{Feature::PreferAggregateBarrierCalls, "preferAggregateBarrierCalls"},
{Feature::PreferCPUForBufferSubData, "preferCPUForBufferSubData"},
{Feature::PreferDeviceLocalMemoryHostVisible, "preferDeviceLocalMemoryHostVisible"},
{Feature::PreferDrawClearOverVkCmdClearAttachments, "preferDrawClearOverVkCmdClearAttachments"},
{Feature::PreferSkippingInvalidateForEmulatedFormats,
"preferSkippingInvalidateForEmulatedFormats"},

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

@ -159,6 +159,7 @@ enum class Feature
PreAddTexelFetchOffsets,
PreferAggregateBarrierCalls,
PreferCPUForBufferSubData,
PreferDeviceLocalMemoryHostVisible,
PreferDrawClearOverVkCmdClearAttachments,
PreferSkippingInvalidateForEmulatedFormats,
PreferSubmitAtFBOBoundary,