blob: 58a5b1f99322f6b7e30269513d4a0bb0287a30cf [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "vulkan_window.h"
#include <stdio.h>
#include "tests/common/utils.h"
#include "tests/common/vk_app_state.h"
#include "tests/common/vk_device_surface_info.h"
#include "tests/common/vk_surface.h"
#include "tests/common/vk_swapchain.h"
#include "tests/common/vk_swapchain_queue.h"
#include "vulkan_device.h"
bool
VulkanWindow::init(VulkanDevice * device, const VulkanWindow::Config & config)
{
device_ = device;
// Allocate display surface, and determine whether it's possible to directly
// render to the swapchain with it.
const vk_surface_config_t surface_config = {
.instance = device->vk_instance(),
.physical_device = device->vk_physical_device(),
.queue_family_index = device->graphics_queue_family(),
.allocator = device->vk_allocator(),
.window_width = config.window_width,
.window_height = config.window_height,
.window_title = config.app_name,
};
surface_ = vk_surface_create(&surface_config);
if (!surface_)
return false; // NOTE: error message already sent to stderr.
VkSurfaceKHR window_surface = vk_surface_get_surface_khr(surface_);
VkImageUsageFlags image_usage = 0;
// Check that rendering directly to the swapchain is supported
if (config.require_swapchain_image_shader_storage)
image_usage |= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (config.require_swapchain_transfers)
image_usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkFormat wanted_format = config.wanted_format;
const vk_swapchain_config_t swapchain_config = {
.instance = device_->vk_instance(),
.device = device_->vk_device(),
.physical_device = device_->vk_physical_device(),
.allocator = device_->vk_allocator(),
.present_queue_family = device_->graphics_queue_family(),
.present_queue_index = 0,
.surface_khr = window_surface,
.max_frames = 3,
.pixel_format = wanted_format,
.disable_vsync = config.disable_vsync,
.image_usage_flags = image_usage,
.staging_mode = config.require_swapchain_image_shader_storage
? VK_SWAPCHAIN_STAGING_MODE_IF_NEEDED
: VK_SWAPCHAIN_STAGING_MODE_NONE,
};
swapchain_ = vk_swapchain_create(&swapchain_config);
// Sanity check.
VkSurfaceFormatKHR surface_format = vk_swapchain_get_format(swapchain_);
if (wanted_format != VK_FORMAT_UNDEFINED && surface_format.format != wanted_format)
{
fprintf(stderr, "WARNING: Could not find wanted pixel format, colors may be wrong!\n");
}
if (config.verbose)
vk_swapchain_print(swapchain_);
info_.image_count = vk_swapchain_get_image_count(swapchain_);
info_.extent = vk_swapchain_get_extent(swapchain_);
info_.surface = window_surface;
info_.surface_format = surface_format;
if (config.enable_swapchain_queue)
{
vk_swapchain_queue_config_t queue_config = {
.swapchain = swapchain_,
.queue_family = device_->graphics_queue_family(),
.queue_index = 0u,
.device = device_->vk_device(),
.allocator = device_->vk_allocator(),
.enable_framebuffers = config.enable_framebuffers,
.sync_semaphores_count = config.sync_semaphores_count,
};
swapchain_queue_ = vk_swapchain_queue_create(&queue_config);
}
return true;
}
VulkanWindow::~VulkanWindow()
{
if (swapchain_queue_)
vk_swapchain_queue_destroy(swapchain_queue_);
if (swapchain_)
vk_swapchain_destroy(swapchain_);
if (surface_)
vk_surface_destroy(surface_);
}
bool
VulkanWindow::acquireSwapchainImage()
{
ASSERT_MSG(!swapchain_queue_, "Calling this method requires enable_swapchain_queue=false");
return vk_swapchain_acquire_next_image(swapchain_, &image_index_);
}
void
VulkanWindow::presentSwapchainImage()
{
ASSERT_MSG(!swapchain_queue_, "Calling this method requires enable_swapchain_queue=false");
vk_swapchain_present_image(swapchain_);
}
bool
VulkanWindow::acquireSwapchainQueueImage()
{
ASSERT_MSG(swapchain_queue_, "Calling this method requires enable_swapchain_queue=true");
swapchain_queue_image_ = vk_swapchain_queue_acquire_next_image(swapchain_queue_);
if (!swapchain_queue_image_)
return false;
image_index_ = vk_swapchain_queue_get_index(swapchain_queue_);
return true;
}
void
VulkanWindow::presentSwapchainQueueImage()
{
ASSERT_MSG(swapchain_queue_, "Calling this method requires enable_swapchain_queue=true");
vk_swapchain_queue_submit_and_present_image(swapchain_queue_);
}
bool
VulkanWindow::handleUserEvents()
{
return vk_surface_poll_events(surface_);
}
void
VulkanWindow::waitIdle()
{
vkDeviceWaitIdle(device_->vk_device());
}