You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
456 lines
20 KiB
456 lines
20 KiB
#include <gtest/gtest.h>
|
|
|
|
#include "CompositorVk.h"
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <glm/gtx/matrix_transform_2d.hpp>
|
|
#include <optional>
|
|
|
|
#include "tests/VkTestUtils.h"
|
|
#include "vulkan/VulkanDispatch.h"
|
|
#include "vulkan/vk_util.h"
|
|
|
|
class CompositorVkTest : public ::testing::Test {
|
|
protected:
|
|
using RenderTarget =
|
|
emugl::RenderResourceVk<VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT>;
|
|
using RenderTexture = emugl::RenderTextureVk;
|
|
|
|
static void SetUpTestCase() { k_vk = emugl::vkDispatch(false); }
|
|
|
|
static constexpr uint32_t k_numOfRenderTargets = 10;
|
|
static constexpr uint32_t k_renderTargetWidth = 255;
|
|
static constexpr uint32_t k_renderTargetHeight = 255;
|
|
static constexpr uint32_t k_renderTargetNumOfPixels =
|
|
k_renderTargetWidth * k_renderTargetHeight;
|
|
|
|
void SetUp() override {
|
|
ASSERT_NE(k_vk, nullptr);
|
|
createInstance();
|
|
pickPhysicalDevice();
|
|
createLogicalDevice();
|
|
|
|
VkFormatProperties formatProperties;
|
|
k_vk->vkGetPhysicalDeviceFormatProperties(
|
|
m_vkPhysicalDevice, RenderTarget::k_vkFormat, &formatProperties);
|
|
if (!(formatProperties.optimalTilingFeatures &
|
|
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
|
|
GTEST_SKIP();
|
|
}
|
|
k_vk->vkGetPhysicalDeviceFormatProperties(
|
|
m_vkPhysicalDevice, RenderTexture::k_vkFormat, &formatProperties);
|
|
if (!(formatProperties.optimalTilingFeatures &
|
|
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
|
|
GTEST_SKIP();
|
|
}
|
|
|
|
VkCommandPoolCreateInfo commandPoolCi = {
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
|
.queueFamilyIndex = m_compositorQueueFamilyIndex};
|
|
ASSERT_EQ(k_vk->vkCreateCommandPool(m_vkDevice, &commandPoolCi, nullptr,
|
|
&m_vkCommandPool),
|
|
VK_SUCCESS);
|
|
k_vk->vkGetDeviceQueue(m_vkDevice, m_compositorQueueFamilyIndex, 0,
|
|
&m_compositorVkQueue);
|
|
ASSERT_TRUE(m_compositorVkQueue != VK_NULL_HANDLE);
|
|
|
|
for (uint32_t i = 0; i < k_numOfRenderTargets; i++) {
|
|
auto renderTarget = RenderTarget::create(
|
|
*k_vk, m_vkDevice, m_vkPhysicalDevice, m_compositorVkQueue,
|
|
m_vkCommandPool, k_renderTargetHeight, k_renderTargetWidth);
|
|
ASSERT_NE(renderTarget, nullptr);
|
|
m_renderTargets.emplace_back(std::move(renderTarget));
|
|
}
|
|
|
|
m_renderTargetImageViews.resize(m_renderTargets.size());
|
|
ASSERT_EQ(
|
|
std::transform(
|
|
m_renderTargets.begin(), m_renderTargets.end(),
|
|
m_renderTargetImageViews.begin(),
|
|
[](const std::unique_ptr<const RenderTarget> &renderTarget) {
|
|
return renderTarget->m_vkImageView;
|
|
}),
|
|
m_renderTargetImageViews.end());
|
|
}
|
|
|
|
void TearDown() override {
|
|
m_renderTargets.clear();
|
|
k_vk->vkDestroyCommandPool(m_vkDevice, m_vkCommandPool, nullptr);
|
|
k_vk->vkDestroyDevice(m_vkDevice, nullptr);
|
|
m_vkDevice = VK_NULL_HANDLE;
|
|
k_vk->vkDestroyInstance(m_vkInstance, nullptr);
|
|
m_vkInstance = VK_NULL_HANDLE;
|
|
}
|
|
|
|
std::unique_ptr<CompositorVk> createCompositor() {
|
|
return CompositorVk::create(
|
|
*k_vk, m_vkDevice, m_vkPhysicalDevice, m_compositorVkQueue,
|
|
RenderTarget::k_vkFormat, RenderTarget::k_vkImageLayout,
|
|
RenderTarget::k_vkImageLayout, k_renderTargetWidth,
|
|
k_renderTargetHeight, m_renderTargetImageViews, m_vkCommandPool);
|
|
}
|
|
|
|
VkSampler createSampler() {
|
|
VkSamplerCreateInfo samplerCi = {
|
|
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
|
.magFilter = VK_FILTER_NEAREST,
|
|
.minFilter = VK_FILTER_NEAREST,
|
|
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
|
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
|
|
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
|
|
.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
|
|
.mipLodBias = 0.0f,
|
|
.anisotropyEnable = VK_FALSE,
|
|
.maxAnisotropy = 1.0f,
|
|
.compareEnable = VK_FALSE,
|
|
.compareOp = VK_COMPARE_OP_ALWAYS,
|
|
.minLod = 0.0f,
|
|
.maxLod = 0.0f,
|
|
.borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,
|
|
.unnormalizedCoordinates = VK_FALSE};
|
|
VkSampler res;
|
|
VK_CHECK(k_vk->vkCreateSampler(m_vkDevice, &samplerCi, nullptr, &res));
|
|
return res;
|
|
}
|
|
|
|
static const goldfish_vk::VulkanDispatch *k_vk;
|
|
VkInstance m_vkInstance = VK_NULL_HANDLE;
|
|
VkPhysicalDevice m_vkPhysicalDevice = VK_NULL_HANDLE;
|
|
uint32_t m_compositorQueueFamilyIndex = 0;
|
|
VkDevice m_vkDevice = VK_NULL_HANDLE;
|
|
std::vector<std::unique_ptr<const RenderTarget>> m_renderTargets;
|
|
std::vector<VkImageView> m_renderTargetImageViews;
|
|
VkCommandPool m_vkCommandPool = VK_NULL_HANDLE;
|
|
VkQueue m_compositorVkQueue = VK_NULL_HANDLE;
|
|
|
|
private:
|
|
void createInstance() {
|
|
VkApplicationInfo appInfo = {
|
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
|
.pNext = nullptr,
|
|
.pApplicationName = "emulator CompositorVk unittest",
|
|
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
|
|
.pEngineName = "No Engine",
|
|
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
|
.apiVersion = VK_API_VERSION_1_1};
|
|
VkInstanceCreateInfo instanceCi = {
|
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
|
.pApplicationInfo = &appInfo,
|
|
.enabledExtensionCount = 0,
|
|
.ppEnabledExtensionNames = nullptr};
|
|
ASSERT_EQ(k_vk->vkCreateInstance(&instanceCi, nullptr, &m_vkInstance),
|
|
VK_SUCCESS);
|
|
ASSERT_TRUE(m_vkInstance != VK_NULL_HANDLE);
|
|
}
|
|
|
|
void pickPhysicalDevice() {
|
|
uint32_t physicalDeviceCount = 0;
|
|
ASSERT_EQ(k_vk->vkEnumeratePhysicalDevices(
|
|
m_vkInstance, &physicalDeviceCount, nullptr),
|
|
VK_SUCCESS);
|
|
ASSERT_GT(physicalDeviceCount, 0);
|
|
std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
|
|
ASSERT_EQ(
|
|
k_vk->vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount,
|
|
physicalDevices.data()),
|
|
VK_SUCCESS);
|
|
for (const auto &device : physicalDevices) {
|
|
VkPhysicalDeviceDescriptorIndexingFeaturesEXT descIndexingFeatures = {
|
|
.sType =
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT};
|
|
VkPhysicalDeviceFeatures2 features = {
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
|
.pNext = &descIndexingFeatures};
|
|
k_vk->vkGetPhysicalDeviceFeatures2(device, &features);
|
|
if (!CompositorVk::validatePhysicalDeviceFeatures(features)) {
|
|
continue;
|
|
}
|
|
uint32_t queueFamilyCount = 0;
|
|
k_vk->vkGetPhysicalDeviceQueueFamilyProperties(
|
|
device, &queueFamilyCount, nullptr);
|
|
ASSERT_GT(queueFamilyCount, 0);
|
|
std::vector<VkQueueFamilyProperties> queueFamilyProperties(
|
|
queueFamilyCount);
|
|
k_vk->vkGetPhysicalDeviceQueueFamilyProperties(
|
|
device, &queueFamilyCount, queueFamilyProperties.data());
|
|
uint32_t queueFamilyIndex = 0;
|
|
for (; queueFamilyIndex < queueFamilyCount; queueFamilyIndex++) {
|
|
if (CompositorVk::validateQueueFamilyProperties(
|
|
queueFamilyProperties[queueFamilyIndex])) {
|
|
break;
|
|
}
|
|
}
|
|
if (queueFamilyIndex == queueFamilyCount) {
|
|
continue;
|
|
}
|
|
|
|
m_compositorQueueFamilyIndex = queueFamilyIndex;
|
|
m_vkPhysicalDevice = device;
|
|
return;
|
|
}
|
|
FAIL() << "Can't find a suitable VkPhysicalDevice.";
|
|
}
|
|
|
|
void createLogicalDevice() {
|
|
const float queuePriority = 1.0f;
|
|
VkDeviceQueueCreateInfo queueCi = {
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
|
.queueFamilyIndex = m_compositorQueueFamilyIndex,
|
|
.queueCount = 1,
|
|
.pQueuePriorities = &queuePriority};
|
|
VkPhysicalDeviceDescriptorIndexingFeaturesEXT descIndexingFeatures = {
|
|
.sType =
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT};
|
|
VkPhysicalDeviceFeatures2 features = {
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
|
.pNext = &descIndexingFeatures};
|
|
ASSERT_TRUE(CompositorVk::enablePhysicalDeviceFeatures(features));
|
|
const std::vector<const char *> enabledDeviceExtensions =
|
|
CompositorVk::getRequiredDeviceExtensions();
|
|
VkDeviceCreateInfo deviceCi = {
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
|
.pNext = &features,
|
|
.queueCreateInfoCount = 1,
|
|
.pQueueCreateInfos = &queueCi,
|
|
.enabledLayerCount = 0,
|
|
.enabledExtensionCount =
|
|
static_cast<uint32_t>(enabledDeviceExtensions.size()),
|
|
.ppEnabledExtensionNames = enabledDeviceExtensions.data()};
|
|
ASSERT_EQ(k_vk->vkCreateDevice(m_vkPhysicalDevice, &deviceCi, nullptr,
|
|
&m_vkDevice),
|
|
VK_SUCCESS);
|
|
ASSERT_TRUE(m_vkDevice != VK_NULL_HANDLE);
|
|
}
|
|
};
|
|
|
|
const goldfish_vk::VulkanDispatch *CompositorVkTest::k_vk = nullptr;
|
|
|
|
TEST_F(CompositorVkTest, Init) { ASSERT_NE(createCompositor(), nullptr); }
|
|
|
|
TEST_F(CompositorVkTest, ValidatePhysicalDeviceFeatures) {
|
|
VkPhysicalDeviceFeatures2 features = {
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
|
|
ASSERT_FALSE(CompositorVk::validatePhysicalDeviceFeatures(features));
|
|
VkPhysicalDeviceDescriptorIndexingFeaturesEXT descIndexingFeatures = {
|
|
.sType =
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT,
|
|
.pNext = &descIndexingFeatures};
|
|
ASSERT_FALSE(CompositorVk::validatePhysicalDeviceFeatures(features));
|
|
descIndexingFeatures.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE;
|
|
ASSERT_TRUE(CompositorVk::validatePhysicalDeviceFeatures(features));
|
|
}
|
|
|
|
TEST_F(CompositorVkTest, ValidateQueueFamilyProperties) {
|
|
VkQueueFamilyProperties properties = {};
|
|
properties.queueFlags &= ~VK_QUEUE_GRAPHICS_BIT;
|
|
ASSERT_FALSE(CompositorVk::validateQueueFamilyProperties(properties));
|
|
properties.queueFlags |= VK_QUEUE_GRAPHICS_BIT;
|
|
ASSERT_TRUE(CompositorVk::validateQueueFamilyProperties(properties));
|
|
}
|
|
|
|
TEST_F(CompositorVkTest, EnablePhysicalDeviceFeatures) {
|
|
VkPhysicalDeviceFeatures2 features = {
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
|
|
ASSERT_FALSE(CompositorVk::enablePhysicalDeviceFeatures(features));
|
|
VkPhysicalDeviceDescriptorIndexingFeaturesEXT descIndexingFeatures = {
|
|
.sType =
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT,
|
|
.pNext = &descIndexingFeatures};
|
|
ASSERT_TRUE(CompositorVk::enablePhysicalDeviceFeatures(features));
|
|
ASSERT_EQ(descIndexingFeatures.descriptorBindingSampledImageUpdateAfterBind,
|
|
VK_TRUE);
|
|
}
|
|
|
|
TEST_F(CompositorVkTest, EmptyCompositionShouldDrawABlackFrame) {
|
|
std::vector<uint32_t> pixels(k_renderTargetNumOfPixels);
|
|
for (uint32_t i = 0; i < k_renderTargetNumOfPixels; i++) {
|
|
uint8_t v = static_cast<uint8_t>((i / 4) & 0xff);
|
|
uint8_t *pixel = reinterpret_cast<uint8_t *>(&pixels[i]);
|
|
pixel[0] = v;
|
|
pixel[1] = v;
|
|
pixel[2] = v;
|
|
pixel[3] = 0xff;
|
|
}
|
|
for (uint32_t i = 0; i < k_numOfRenderTargets; i++) {
|
|
ASSERT_TRUE(m_renderTargets[i]->write(pixels));
|
|
auto maybeImageBytes = m_renderTargets[i]->read();
|
|
ASSERT_TRUE(maybeImageBytes.has_value());
|
|
for (uint32_t i = 0; i < k_renderTargetNumOfPixels; i++) {
|
|
ASSERT_EQ(pixels[i], maybeImageBytes.value()[i]);
|
|
}
|
|
}
|
|
|
|
auto compositor = createCompositor();
|
|
ASSERT_NE(compositor, nullptr);
|
|
|
|
// render to render targets with event index
|
|
std::vector<VkCommandBuffer> cmdBuffs = {};
|
|
for (uint32_t i = 0; i < k_numOfRenderTargets; i++) {
|
|
if (i % 2 == 0) {
|
|
cmdBuffs.emplace_back(compositor->getCommandBuffer(i));
|
|
}
|
|
}
|
|
VkSubmitInfo submitInfo = {
|
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
|
.commandBufferCount = static_cast<uint32_t>(cmdBuffs.size()),
|
|
.pCommandBuffers = cmdBuffs.data()};
|
|
ASSERT_EQ(k_vk->vkQueueSubmit(m_compositorVkQueue, 1, &submitInfo,
|
|
VK_NULL_HANDLE),
|
|
VK_SUCCESS);
|
|
|
|
ASSERT_EQ(k_vk->vkQueueWaitIdle(m_compositorVkQueue), VK_SUCCESS);
|
|
for (uint32_t i = 0; i < k_numOfRenderTargets; i++) {
|
|
auto maybeImagePixels = m_renderTargets[i]->read();
|
|
ASSERT_TRUE(maybeImagePixels.has_value());
|
|
const auto &imagePixels = maybeImagePixels.value();
|
|
for (uint32_t j = 0; j < k_renderTargetNumOfPixels; j++) {
|
|
const auto pixel =
|
|
reinterpret_cast<const uint8_t *>(&imagePixels[j]);
|
|
// should only render to render targets with even index
|
|
if (i % 2 == 0) {
|
|
ASSERT_EQ(pixel[0], 0);
|
|
ASSERT_EQ(pixel[1], 0);
|
|
ASSERT_EQ(pixel[2], 0);
|
|
ASSERT_EQ(pixel[3], 0xff);
|
|
} else {
|
|
ASSERT_EQ(pixels[j], imagePixels[j]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(CompositorVkTest, SimpleComposition) {
|
|
constexpr uint32_t textureLeft = 30;
|
|
constexpr uint32_t textureRight = 50;
|
|
constexpr uint32_t textureTop = 10;
|
|
constexpr uint32_t textureBottom = 40;
|
|
constexpr uint32_t textureWidth = textureRight - textureLeft;
|
|
constexpr uint32_t textureHeight = textureBottom - textureTop;
|
|
auto sampler = createSampler();
|
|
auto texture = RenderTexture::create(*k_vk, m_vkDevice, m_vkPhysicalDevice,
|
|
m_compositorVkQueue, m_vkCommandPool,
|
|
textureWidth, textureHeight);
|
|
uint32_t textureColor;
|
|
uint8_t *textureColor_ = reinterpret_cast<uint8_t *>(&textureColor);
|
|
textureColor_[0] = 0xff;
|
|
textureColor_[1] = 0;
|
|
textureColor_[2] = 0;
|
|
textureColor_[3] = 0xff;
|
|
std::vector<uint32_t> pixels(textureWidth * textureHeight, textureColor);
|
|
ASSERT_TRUE(texture->write(pixels));
|
|
auto compositor = createCompositor();
|
|
ASSERT_NE(compositor, nullptr);
|
|
auto composition = std::make_unique<Composition>(
|
|
texture->m_vkImageView, sampler, textureWidth, textureHeight);
|
|
auto transform = glm::translate(glm::mat3(1.0f),
|
|
glm::vec2(static_cast<float>(textureLeft),
|
|
static_cast<float>(textureTop)));
|
|
composition->m_transform = transform;
|
|
compositor->setComposition(0, std::move(composition));
|
|
VkCommandBuffer cmdBuff = compositor->getCommandBuffer(0);
|
|
VkSubmitInfo submitInfo = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
|
.commandBufferCount = 1,
|
|
.pCommandBuffers = &cmdBuff};
|
|
ASSERT_EQ(k_vk->vkQueueSubmit(m_compositorVkQueue, 1, &submitInfo,
|
|
VK_NULL_HANDLE),
|
|
VK_SUCCESS);
|
|
ASSERT_EQ(k_vk->vkQueueWaitIdle(m_compositorVkQueue), VK_SUCCESS);
|
|
|
|
auto maybeImagePixels = m_renderTargets[0]->read();
|
|
ASSERT_TRUE(maybeImagePixels.has_value());
|
|
const auto &imagePixels = maybeImagePixels.value();
|
|
|
|
for (uint32_t i = 0; i < k_renderTargetHeight; i++) {
|
|
for (uint32_t j = 0; j < k_renderTargetWidth; j++) {
|
|
uint32_t offset = i * k_renderTargetWidth + j;
|
|
const uint8_t *pixel =
|
|
reinterpret_cast<const uint8_t *>(&imagePixels[offset]);
|
|
EXPECT_EQ(pixel[1], 0);
|
|
EXPECT_EQ(pixel[2], 0);
|
|
EXPECT_EQ(pixel[3], 0xff);
|
|
if (i >= textureTop && i < textureBottom && j >= textureLeft &&
|
|
j < textureRight) {
|
|
EXPECT_EQ(pixel[0], 0xff);
|
|
} else {
|
|
EXPECT_EQ(pixel[0], 0);
|
|
}
|
|
}
|
|
}
|
|
k_vk->vkDestroySampler(m_vkDevice, sampler, nullptr);
|
|
}
|
|
|
|
TEST_F(CompositorVkTest, CompositingWithDifferentCompositionOnMultipleTargets) {
|
|
constexpr uint32_t textureWidth = 20;
|
|
constexpr uint32_t textureHeight = 30;
|
|
struct Rect {
|
|
uint32_t m_top;
|
|
uint32_t m_bottom;
|
|
uint32_t m_left;
|
|
uint32_t m_right;
|
|
};
|
|
std::vector<Rect> texturePositions(k_numOfRenderTargets);
|
|
for (int i = 0; i < k_numOfRenderTargets; i++) {
|
|
auto left = (i * 30) % (k_renderTargetWidth - textureWidth);
|
|
auto top = (i * 20) % (k_renderTargetHeight - textureHeight);
|
|
texturePositions[i].m_top = top;
|
|
texturePositions[i].m_bottom = top + textureHeight;
|
|
texturePositions[i].m_left = left;
|
|
texturePositions[i].m_right = left + textureWidth;
|
|
}
|
|
auto sampler = createSampler();
|
|
auto texture = RenderTexture::create(*k_vk, m_vkDevice, m_vkPhysicalDevice,
|
|
m_compositorVkQueue, m_vkCommandPool,
|
|
textureWidth, textureHeight);
|
|
uint32_t textureColor;
|
|
uint8_t *textureColor_ = reinterpret_cast<uint8_t *>(&textureColor);
|
|
textureColor_[0] = 0xff;
|
|
textureColor_[1] = 0;
|
|
textureColor_[2] = 0;
|
|
textureColor_[3] = 0xff;
|
|
std::vector<uint32_t> pixels(textureWidth * textureHeight, textureColor);
|
|
ASSERT_TRUE(texture->write(pixels));
|
|
auto compositor = createCompositor();
|
|
ASSERT_NE(compositor, nullptr);
|
|
for (int i = 0; i < k_numOfRenderTargets; i++) {
|
|
const auto &pos = texturePositions[i];
|
|
auto composition = std::make_unique<Composition>(
|
|
texture->m_vkImageView, sampler, textureWidth, textureHeight);
|
|
auto transform = glm::translate(
|
|
glm::mat3(1.0f), glm::vec2(static_cast<float>(pos.m_left),
|
|
static_cast<float>(pos.m_top)));
|
|
composition->m_transform = transform;
|
|
compositor->setComposition(i, std::move(composition));
|
|
VkCommandBuffer cmdBuff = compositor->getCommandBuffer(i);
|
|
VkSubmitInfo submitInfo = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
|
.commandBufferCount = 1,
|
|
.pCommandBuffers = &cmdBuff};
|
|
ASSERT_EQ(k_vk->vkQueueSubmit(m_compositorVkQueue, 1, &submitInfo,
|
|
VK_NULL_HANDLE),
|
|
VK_SUCCESS);
|
|
ASSERT_EQ(k_vk->vkQueueWaitIdle(m_compositorVkQueue), VK_SUCCESS);
|
|
|
|
auto maybeImagePixels = m_renderTargets[i]->read();
|
|
ASSERT_TRUE(maybeImagePixels.has_value());
|
|
const auto &imagePixels = maybeImagePixels.value();
|
|
|
|
for (uint32_t i = 0; i < k_renderTargetHeight; i++) {
|
|
for (uint32_t j = 0; j < k_renderTargetWidth; j++) {
|
|
uint32_t offset = i * k_renderTargetWidth + j;
|
|
const uint8_t *pixel =
|
|
reinterpret_cast<const uint8_t *>(&imagePixels[offset]);
|
|
EXPECT_EQ(pixel[1], 0);
|
|
EXPECT_EQ(pixel[2], 0);
|
|
EXPECT_EQ(pixel[3], 0xff);
|
|
if (i >= pos.m_top && i < pos.m_bottom && j >= pos.m_left &&
|
|
j < pos.m_right) {
|
|
EXPECT_EQ(pixel[0], 0xff);
|
|
} else {
|
|
EXPECT_EQ(pixel[0], 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
k_vk->vkDestroySampler(m_vkDevice, sampler, nullptr);
|
|
} |