aboutsummaryrefslogtreecommitdiff
path: root/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp')
-rw-r--r--common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp b/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp
new file mode 100644
index 00000000..af0a75f2
--- /dev/null
+++ b/common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp
@@ -0,0 +1,228 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+
+#include "GfxstreamEnd2EndTests.h"
+#include "gfxstream/RutabagaLayerTestUtils.h"
+
+namespace gfxstream {
+namespace tests {
+namespace {
+
+using testing::Eq;
+using testing::Ge;
+using testing::IsEmpty;
+using testing::IsNull;
+using testing::Not;
+using testing::NotNull;
+
+class GfxstreamEnd2EndVkSnapshotBufferTest : public GfxstreamEnd2EndTest {};
+
+TEST_P(GfxstreamEnd2EndVkSnapshotBufferTest, BufferContent) {
+ static constexpr vkhpp::DeviceSize kSize = 256;
+
+ std::vector<uint8_t> srcBufferContent(kSize);
+ for (size_t i = 0; i < kSize; i++) {
+ srcBufferContent[i] = static_cast<uint8_t>(i & 0xff);
+ }
+ auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
+ VK_ASSERT(SetUpTypicalVkTestEnvironment());
+
+ // Staging buffer
+ const vkhpp::BufferCreateInfo stagingBufferCreateInfo = {
+ .size = static_cast<VkDeviceSize>(kSize),
+ .usage = vkhpp::BufferUsageFlagBits::eTransferSrc,
+ .sharingMode = vkhpp::SharingMode::eExclusive,
+ };
+ auto stagingBuffer = device->createBufferUnique(stagingBufferCreateInfo).value;
+ ASSERT_THAT(stagingBuffer, IsValidHandle());
+
+ vkhpp::MemoryRequirements stagingBufferMemoryRequirements{};
+ device->getBufferMemoryRequirements(*stagingBuffer, &stagingBufferMemoryRequirements);
+
+ const auto stagingBufferMemoryType = GetMemoryType(
+ physicalDevice, stagingBufferMemoryRequirements,
+ vkhpp::MemoryPropertyFlagBits::eHostVisible | vkhpp::MemoryPropertyFlagBits::eHostCoherent);
+
+ // Staging memory
+ const vkhpp::MemoryAllocateInfo stagingBufferMemoryAllocateInfo = {
+ .allocationSize = stagingBufferMemoryRequirements.size,
+ .memoryTypeIndex = stagingBufferMemoryType,
+ };
+ auto stagingBufferMemory = device->allocateMemoryUnique(stagingBufferMemoryAllocateInfo).value;
+ ASSERT_THAT(stagingBufferMemory, IsValidHandle());
+ ASSERT_THAT(device->bindBufferMemory(*stagingBuffer, *stagingBufferMemory, 0), IsVkSuccess());
+
+ // Fill memory content
+ void* mapped = nullptr;
+ auto mapResult =
+ device->mapMemory(*stagingBufferMemory, 0, VK_WHOLE_SIZE, vkhpp::MemoryMapFlags{}, &mapped);
+ ASSERT_THAT(mapResult, IsVkSuccess());
+ ASSERT_THAT(mapped, NotNull());
+
+ auto* bytes = reinterpret_cast<uint8_t*>(mapped);
+ std::memcpy(bytes, srcBufferContent.data(), kSize);
+
+ const vkhpp::MappedMemoryRange range = {
+ .memory = *stagingBufferMemory,
+ .offset = 0,
+ .size = kSize,
+ };
+ device->unmapMemory(*stagingBufferMemory);
+
+ // Vertex buffer
+ const vkhpp::BufferCreateInfo vertexBufferCreateInfo = {
+ .size = static_cast<VkDeviceSize>(kSize),
+ .usage = vkhpp::BufferUsageFlagBits::eVertexBuffer,
+ .sharingMode = vkhpp::SharingMode::eExclusive,
+ };
+ auto vertexBuffer = device->createBufferUnique(vertexBufferCreateInfo).value;
+ ASSERT_THAT(vertexBuffer, IsValidHandle());
+
+ vkhpp::MemoryRequirements vertexBufferMemoryRequirements{};
+ device->getBufferMemoryRequirements(*vertexBuffer, &vertexBufferMemoryRequirements);
+
+ const auto vertexBufferMemoryType = GetMemoryType(
+ physicalDevice, vertexBufferMemoryRequirements,
+ vkhpp::MemoryPropertyFlagBits::eHostVisible | vkhpp::MemoryPropertyFlagBits::eHostCoherent);
+
+ // Vertex memory
+ const vkhpp::MemoryAllocateInfo vertexBufferMemoryAllocateInfo = {
+ .allocationSize = vertexBufferMemoryRequirements.size,
+ .memoryTypeIndex = vertexBufferMemoryType,
+ };
+ auto vertexBufferMemory = device->allocateMemoryUnique(vertexBufferMemoryAllocateInfo).value;
+ ASSERT_THAT(vertexBufferMemory, IsValidHandle());
+ ASSERT_THAT(device->bindBufferMemory(*vertexBuffer, *vertexBufferMemory, 0), IsVkSuccess());
+
+ // Command buffer
+ const vkhpp::CommandPoolCreateInfo commandPoolCreateInfo = {
+ .queueFamilyIndex = queueFamilyIndex,
+ };
+
+ auto commandPool = device->createCommandPoolUnique(commandPoolCreateInfo).value;
+ ASSERT_THAT(commandPool, IsValidHandle());
+
+ const vkhpp::CommandBufferAllocateInfo commandBufferAllocateInfo = {
+ .level = vkhpp::CommandBufferLevel::ePrimary,
+ .commandPool = *commandPool,
+ .commandBufferCount = 1,
+ };
+ auto commandBuffers = device->allocateCommandBuffersUnique(commandBufferAllocateInfo).value;
+ ASSERT_THAT(commandBuffers, Not(IsEmpty()));
+ auto commandBuffer = std::move(commandBuffers[0]);
+ ASSERT_THAT(commandBuffer, IsValidHandle());
+
+ const vkhpp::CommandBufferBeginInfo commandBufferBeginInfo = {
+ .flags = vkhpp::CommandBufferUsageFlagBits::eOneTimeSubmit,
+ };
+ commandBuffer->begin(commandBufferBeginInfo);
+ const vkhpp::BufferCopy bufferCopy = {
+ .size = kSize,
+ };
+ commandBuffer->copyBuffer(*stagingBuffer, *vertexBuffer, 1, &bufferCopy);
+ commandBuffer->end();
+
+ auto transferFence = device->createFenceUnique(vkhpp::FenceCreateInfo()).value;
+ ASSERT_THAT(transferFence, IsValidHandle());
+
+ // Execute the command to copy image
+ const vkhpp::SubmitInfo submitInfo = {
+ .commandBufferCount = 1,
+ .pCommandBuffers = &commandBuffer.get(),
+ };
+ queue.submit(submitInfo, *transferFence);
+
+ auto waitResult = device->waitForFences(*transferFence, VK_TRUE, 3000000000L);
+ ASSERT_THAT(waitResult, IsVkSuccess());
+
+ // Snapshot
+ SnapshotSaveAndLoad();
+
+ // Read-back buffer
+ const vkhpp::BufferCreateInfo readbackBufferCreateInfo = {
+ .size = static_cast<VkDeviceSize>(kSize),
+ .usage = vkhpp::BufferUsageFlagBits::eTransferDst,
+ .sharingMode = vkhpp::SharingMode::eExclusive,
+ };
+ auto readbackBuffer = device->createBufferUnique(readbackBufferCreateInfo).value;
+ ASSERT_THAT(readbackBuffer, IsValidHandle());
+
+ vkhpp::MemoryRequirements readbackBufferMemoryRequirements{};
+ device->getBufferMemoryRequirements(*readbackBuffer, &readbackBufferMemoryRequirements);
+
+ const auto readbackBufferMemoryType = GetMemoryType(
+ physicalDevice, readbackBufferMemoryRequirements,
+ vkhpp::MemoryPropertyFlagBits::eHostVisible | vkhpp::MemoryPropertyFlagBits::eHostCoherent);
+
+ // Read-back memory
+ const vkhpp::MemoryAllocateInfo readbackBufferMemoryAllocateInfo = {
+ .allocationSize = readbackBufferMemoryRequirements.size,
+ .memoryTypeIndex = readbackBufferMemoryType,
+ };
+ auto readbackBufferMemory =
+ device->allocateMemoryUnique(readbackBufferMemoryAllocateInfo).value;
+ ASSERT_THAT(readbackBufferMemory, IsValidHandle());
+ ASSERT_THAT(device->bindBufferMemory(*readbackBuffer, *readbackBufferMemory, 0), IsVkSuccess());
+
+ auto readbackCommandBuffers =
+ device->allocateCommandBuffersUnique(commandBufferAllocateInfo).value;
+ ASSERT_THAT(readbackCommandBuffers, Not(IsEmpty()));
+ auto readbackCommandBuffer = std::move(readbackCommandBuffers[0]);
+ ASSERT_THAT(readbackCommandBuffer, IsValidHandle());
+
+ readbackCommandBuffer->begin(commandBufferBeginInfo);
+ readbackCommandBuffer->copyBuffer(*vertexBuffer, *readbackBuffer, 1, &bufferCopy);
+ readbackCommandBuffer->end();
+
+ auto readbackFence = device->createFenceUnique(vkhpp::FenceCreateInfo()).value;
+ ASSERT_THAT(readbackCommandBuffer, IsValidHandle());
+
+ // Execute the command to copy image back to buffer
+ const vkhpp::SubmitInfo readbackSubmitInfo = {
+ .commandBufferCount = 1,
+ .pCommandBuffers = &readbackCommandBuffer.get(),
+ };
+ queue.submit(readbackSubmitInfo, *readbackFence);
+
+ auto readbackWaitResult = device->waitForFences(*readbackFence, VK_TRUE, 3000000000L);
+ ASSERT_THAT(readbackWaitResult, IsVkSuccess());
+
+ // Verify content
+ mapResult = device->mapMemory(*readbackBufferMemory, 0, VK_WHOLE_SIZE, vkhpp::MemoryMapFlags{},
+ &mapped);
+ ASSERT_THAT(mapResult, IsVkSuccess());
+ ASSERT_THAT(mapped, NotNull());
+ bytes = reinterpret_cast<uint8_t*>(mapped);
+
+ for (uint32_t i = 0; i < kSize; ++i) {
+ ASSERT_THAT(bytes[i], Eq(srcBufferContent[i]));
+ }
+ device->unmapMemory(*readbackBufferMemory);
+}
+
+INSTANTIATE_TEST_CASE_P(GfxstreamEnd2EndTests, GfxstreamEnd2EndVkSnapshotBufferTest,
+ ::testing::ValuesIn({
+ TestParams{
+ .with_gl = false,
+ .with_vk = true,
+ .with_features = {"VulkanSnapshots"},
+ },
+ }),
+ &GetTestName);
+
+} // namespace
+} // namespace tests
+} // namespace gfxstream \ No newline at end of file