зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
d988db39b0
Коммит
3b38b37907
|
@ -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,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()))))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче