diff --git a/include/platform/FeaturesVk.h b/include/platform/FeaturesVk.h
index 0c0e930e8..548af6b59 100644
--- a/include/platform/FeaturesVk.h
+++ b/include/platform/FeaturesVk.h
@@ -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;
diff --git a/include/platform/vk_features.json b/include/platform/vk_features.json
index 1ca9d8b8c..3990394e4 100644
--- a/include/platform/vk_features.json
+++ b/include/platform/vk_features.json
@@ -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"
         }
     ]
 }
diff --git a/scripts/code_generation_hashes/ANGLE_features.json b/scripts/code_generation_hashes/ANGLE_features.json
index 3c244996a..652ac3e58 100644
--- a/scripts/code_generation_hashes/ANGLE_features.json
+++ b/scripts/code_generation_hashes/ANGLE_features.json
@@ -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"
 }
\ No newline at end of file
diff --git a/src/libANGLE/renderer/vulkan/BufferVk.cpp b/src/libANGLE/renderer/vulkan/BufferVk.cpp
index 115121edd..28ce227e4 100644
--- a/src/libANGLE/renderer/vulkan/BufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/BufferVk.cpp
@@ -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,11 +622,16 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk,
                                      GLbitfield access,
                                      void **mapPtr)
 {
-    uint8_t **mapPtrBytes = reinterpret_cast<uint8_t **>(mapPtr);
-
     ASSERT(mBuffer.valid());
 
-    bool hostVisible = mBuffer.isHostVisible();
+    // 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.
     if ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0)
@@ -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()))))
         {
diff --git a/src/libANGLE/renderer/vulkan/BufferVk.h b/src/libANGLE/renderer/vulkan/BufferVk.h
index 516bfb13d..5c5fa86ed 100644
--- a/src/libANGLE/renderer/vulkan/BufferVk.h
+++ b/src/libANGLE/renderer/vulkan/BufferVk.h
@@ -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
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index b0b05c0b5..38f4d7dd9 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -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
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
index 426508af5..32e7059f3 100644
--- a/src/tests/angle_end2end_tests_expectations.txt
+++ b/src/tests/angle_end2end_tests_expectations.txt
@@ -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
diff --git a/src/tests/gl_tests/ComputeShaderTest.cpp b/src/tests/gl_tests/ComputeShaderTest.cpp
index 8a2bd631b..d149971de 100644
--- a/src/tests/gl_tests/ComputeShaderTest.cpp
+++ b/src/tests/gl_tests/ComputeShaderTest.cpp
@@ -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);
diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp
index eb450d23f..ee1a71042 100644
--- a/src/tests/gl_tests/GLSLTest.cpp
+++ b/src/tests/gl_tests/GLSLTest.cpp
@@ -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;
diff --git a/src/tests/gl_tests/ReadPixelsTest.cpp b/src/tests/gl_tests/ReadPixelsTest.cpp
index d7a20ab59..172e9129a 100644
--- a/src/tests/gl_tests/ReadPixelsTest.cpp
+++ b/src/tests/gl_tests/ReadPixelsTest.cpp
@@ -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);
@@ -110,11 +111,12 @@ class ReadPixelsPBONVTest : public ReadPixelsTest
                IsGLExtensionEnabled("GL_EXT_texture_storage");
     }
 
-    GLuint mPBO       = 0;
-    GLuint mTexture   = 0;
-    GLuint mFBO       = 0;
-    GLuint mFBOWidth  = 0;
-    GLuint mFBOHeight = 0;
+    GLuint mPBO           = 0;
+    GLuint mTexture       = 0;
+    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();
 
diff --git a/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp b/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp
index b777782d7..66b36254c 100644
--- a/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp
+++ b/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp
@@ -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;
diff --git a/util/angle_features_autogen.cpp b/util/angle_features_autogen.cpp
index d222eecb2..351b9b6ea 100644
--- a/util/angle_features_autogen.cpp
+++ b/util/angle_features_autogen.cpp
@@ -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"},
diff --git a/util/angle_features_autogen.h b/util/angle_features_autogen.h
index a0205f5d9..c1a916cf7 100644
--- a/util/angle_features_autogen.h
+++ b/util/angle_features_autogen.h
@@ -159,6 +159,7 @@ enum class Feature
     PreAddTexelFetchOffsets,
     PreferAggregateBarrierCalls,
     PreferCPUForBufferSubData,
+    PreferDeviceLocalMemoryHostVisible,
     PreferDrawClearOverVkCmdClearAttachments,
     PreferSkippingInvalidateForEmulatedFormats,
     PreferSubmitAtFBOBoundary,