diff options
Diffstat (limited to 'common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp')
-rw-r--r-- | common/end2end/GfxstreamEnd2EndVkSnapshotBufferTests.cpp | 228 |
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 |