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,