fix for AMD gpu (#21)

This commit is contained in:
InoriRus 2022-07-04 17:24:03 +03:00
parent 1aa7cf72ce
commit 498eac6a32
8 changed files with 345 additions and 186 deletions

View File

@ -1,4 +1,4 @@
version: 0.1.7.build-{build}
version: 0.1.8.build-{build}
image: Visual Studio 2019
environment:
matrix:

View File

@ -82,7 +82,7 @@ if (KYTY_LINKER STREQUAL LD)
set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000")
endif()
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.1.7)
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.1.8)
include(src_script.cmake)

View File

@ -38,23 +38,33 @@ struct VulkanCommandPool
uint32_t buffers_count = 0;
};
struct VulkanQueueInfo
{
Core::Mutex* mutex = nullptr;
uint32_t family = static_cast<uint32_t>(-1);
uint32_t index = static_cast<uint32_t>(-1);
VkQueue vk_queue = nullptr;
};
struct GraphicContext
{
static constexpr int QUEUES_NUM = 11;
static constexpr int QUEUE_GFX = 8;
static constexpr int QUEUE_GFX_NUM = 1;
static constexpr int QUEUE_UTIL = 9;
static constexpr int QUEUE_UTIL_NUM = 1;
static constexpr int QUEUE_PRESENT = 10;
static constexpr int QUEUE_PRESENT_NUM = 1;
static constexpr int QUEUE_COMPUTE_START = 0;
static constexpr int QUEUE_COMPUTE_NUM = 8;
uint32_t screen_width = 0;
uint32_t screen_height = 0;
VkInstance instance = nullptr;
VkDebugUtilsMessengerEXT debug_messenger = nullptr;
VkPhysicalDevice physical_device = nullptr;
VkDevice device = nullptr;
uint32_t queue_family_index = static_cast<uint32_t>(-1);
VkQueue queue[QUEUES_NUM] = {};
uint32_t screen_width = 0;
uint32_t screen_height = 0;
VkInstance instance = nullptr;
VkDebugUtilsMessengerEXT debug_messenger = nullptr;
VkPhysicalDevice physical_device = nullptr;
VkDevice device = nullptr;
VulkanQueueInfo queues[QUEUES_NUM];
};
struct VulkanMemory

View File

@ -30,7 +30,7 @@ struct RenderColorInfo;
class CommandBuffer
{
public:
CommandBuffer() { Allocate(); }
explicit CommandBuffer(int queue): m_queue(queue) { Allocate(); }
virtual ~CommandBuffer() { Free(); }
void SetParent(CommandProcessor* parent) { m_parent = parent; }
@ -55,9 +55,6 @@ public:
VulkanCommandPool* GetPool() { return m_pool; }
[[nodiscard]] bool IsExecute() const { return m_execute; }
void SetQueue(int queue) { m_queue = queue; }
// void CommandProcessorWait();
private:
VulkanCommandPool* m_pool = nullptr;

View File

@ -434,31 +434,28 @@ class CommandPool
{
public:
CommandPool() = default;
~CommandPool()
~CommandPool() // NOLINT
{
if (m_pool != nullptr)
{
// TODO(): check if destructor is called from std::_Exit()
// Delete();
}
// TODO(): check if destructor is called from std::_Exit()
// DeleteAll();
}
KYTY_CLASS_NO_COPY(CommandPool);
VulkanCommandPool* GetPool()
VulkanCommandPool* GetPool(int id)
{
if (m_pool == nullptr)
if (m_pool[id] == nullptr)
{
Create();
Create(id);
}
return m_pool;
return m_pool[id];
}
private:
void Create();
void Delete();
void Create(int id);
void DeleteAll();
VulkanCommandPool* m_pool = nullptr;
VulkanCommandPool* m_pool[GraphicContext::QUEUES_NUM] = {};
};
static RenderContext* g_render_ctx = nullptr;
@ -1190,60 +1187,61 @@ VulkanBuffer* GdsBuffer::GetBuffer(GraphicContext* ctx)
return m_buffer;
}
void CommandPool::Create()
void CommandPool::Create(int id)
{
auto* ctx = g_render_ctx->GetGraphicCtx();
EXIT_IF(m_pool != nullptr);
EXIT_IF(id < 0 || id >= GraphicContext::QUEUES_NUM);
EXIT_IF(m_pool[id] != nullptr);
m_pool = new VulkanCommandPool;
m_pool[id] = new VulkanCommandPool;
EXIT_IF(ctx == nullptr);
EXIT_IF(ctx->device == nullptr);
EXIT_IF(ctx->queue_family_index == static_cast<uint32_t>(-1));
EXIT_IF(m_pool->pool != nullptr);
EXIT_IF(m_pool->buffers != nullptr);
EXIT_IF(m_pool->fences != nullptr);
EXIT_IF(m_pool->semaphores != nullptr);
EXIT_IF(m_pool->buffers_count != 0);
EXIT_IF(ctx->queues[id].family == static_cast<uint32_t>(-1));
EXIT_IF(m_pool[id]->pool != nullptr);
EXIT_IF(m_pool[id]->buffers != nullptr);
EXIT_IF(m_pool[id]->fences != nullptr);
EXIT_IF(m_pool[id]->semaphores != nullptr);
EXIT_IF(m_pool[id]->buffers_count != 0);
VkCommandPoolCreateInfo pool_info {};
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_info.pNext = nullptr;
pool_info.queueFamilyIndex = ctx->queue_family_index;
pool_info.queueFamilyIndex = ctx->queues[id].family;
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
vkCreateCommandPool(ctx->device, &pool_info, nullptr, &m_pool->pool);
vkCreateCommandPool(ctx->device, &pool_info, nullptr, &m_pool[id]->pool);
EXIT_NOT_IMPLEMENTED(m_pool->pool == nullptr);
EXIT_NOT_IMPLEMENTED(m_pool[id]->pool == nullptr);
m_pool->buffers_count = 4;
m_pool->buffers = new VkCommandBuffer[m_pool->buffers_count];
m_pool->fences = new VkFence[m_pool->buffers_count];
m_pool->semaphores = new VkSemaphore[m_pool->buffers_count];
m_pool->busy = new bool[m_pool->buffers_count];
m_pool[id]->buffers_count = 4;
m_pool[id]->buffers = new VkCommandBuffer[m_pool[id]->buffers_count];
m_pool[id]->fences = new VkFence[m_pool[id]->buffers_count];
m_pool[id]->semaphores = new VkSemaphore[m_pool[id]->buffers_count];
m_pool[id]->busy = new bool[m_pool[id]->buffers_count];
VkCommandBufferAllocateInfo alloc_info {};
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
alloc_info.commandPool = m_pool->pool;
alloc_info.commandPool = m_pool[id]->pool;
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
alloc_info.commandBufferCount = m_pool->buffers_count;
alloc_info.commandBufferCount = m_pool[id]->buffers_count;
if (vkAllocateCommandBuffers(ctx->device, &alloc_info, m_pool->buffers) != VK_SUCCESS)
if (vkAllocateCommandBuffers(ctx->device, &alloc_info, m_pool[id]->buffers) != VK_SUCCESS)
{
EXIT("Can't allocate command buffers");
}
for (uint32_t i = 0; i < m_pool->buffers_count; i++)
for (uint32_t i = 0; i < m_pool[id]->buffers_count; i++)
{
m_pool->busy[i] = false;
m_pool[id]->busy[i] = false;
VkFenceCreateInfo fence_info {};
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_info.pNext = nullptr;
fence_info.flags = 0;
if (vkCreateFence(ctx->device, &fence_info, nullptr, &m_pool->fences[i]) != VK_SUCCESS)
if (vkCreateFence(ctx->device, &fence_info, nullptr, &m_pool[id]->fences[i]) != VK_SUCCESS)
{
EXIT("Can't create fence");
}
@ -1253,42 +1251,47 @@ void CommandPool::Create()
semaphore_info.pNext = nullptr;
semaphore_info.flags = 0;
if (vkCreateSemaphore(ctx->device, &semaphore_info, nullptr, &m_pool->semaphores[i]) != VK_SUCCESS)
if (vkCreateSemaphore(ctx->device, &semaphore_info, nullptr, &m_pool[id]->semaphores[i]) != VK_SUCCESS)
{
EXIT("Can't create semaphore");
}
EXIT_IF(m_pool->buffers[i] == nullptr);
EXIT_IF(m_pool->fences[i] == nullptr);
EXIT_IF(m_pool->semaphores[i] == nullptr);
EXIT_IF(m_pool[id]->buffers[i] == nullptr);
EXIT_IF(m_pool[id]->fences[i] == nullptr);
EXIT_IF(m_pool[id]->semaphores[i] == nullptr);
}
}
void CommandPool::Delete()
void CommandPool::DeleteAll()
{
auto* ctx = g_render_ctx->GetGraphicCtx();
EXIT_IF(m_pool == nullptr);
EXIT_IF(ctx == nullptr);
EXIT_IF(ctx->device == nullptr);
for (uint32_t i = 0; i < m_pool->buffers_count; i++)
for (auto& pool: m_pool)
{
vkDestroySemaphore(ctx->device, m_pool->semaphores[i], nullptr);
vkDestroyFence(ctx->device, m_pool->fences[i], nullptr);
if (pool != nullptr)
{
EXIT_IF(ctx == nullptr);
EXIT_IF(ctx->device == nullptr);
for (uint32_t i = 0; i < pool->buffers_count; i++)
{
vkDestroySemaphore(ctx->device, pool->semaphores[i], nullptr);
vkDestroyFence(ctx->device, pool->fences[i], nullptr);
}
vkFreeCommandBuffers(ctx->device, pool->pool, pool->buffers_count, pool->buffers);
vkDestroyCommandPool(ctx->device, pool->pool, nullptr);
delete[] pool->semaphores;
delete[] pool->fences;
delete[] pool->buffers;
delete[] pool->busy;
delete pool;
pool = nullptr;
}
}
vkFreeCommandBuffers(ctx->device, m_pool->pool, m_pool->buffers_count, m_pool->buffers);
vkDestroyCommandPool(ctx->device, m_pool->pool, nullptr);
delete[] m_pool->semaphores;
delete[] m_pool->fences;
delete[] m_pool->buffers;
delete[] m_pool->busy;
delete m_pool;
m_pool = nullptr;
}
VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* color, RenderDepthInfo* depth)
@ -5049,7 +5052,7 @@ void CommandBuffer::Allocate()
{
EXIT_IF(!IsInvalid());
m_pool = g_command_pool.GetPool();
m_pool = g_command_pool.GetPool(m_queue);
Core::LockGuard lock(m_pool->mutex);
@ -5130,9 +5133,19 @@ void CommandBuffer::Execute()
EXIT_IF(m_queue < 0 || m_queue >= GraphicContext::QUEUES_NUM);
auto* queue = g_render_ctx->GetGraphicCtx()->queue[m_queue];
const auto& queue = g_render_ctx->GetGraphicCtx()->queues[m_queue];
auto result = vkQueueSubmit(queue, 1, &submit_info, fence);
if (queue.mutex != nullptr)
{
queue.mutex->Lock();
}
auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
if (queue.mutex != nullptr)
{
queue.mutex->Unlock();
}
m_execute = true;
@ -5159,9 +5172,19 @@ void CommandBuffer::ExecuteWithSemaphore()
EXIT_IF(m_queue < 0 || m_queue >= GraphicContext::QUEUES_NUM);
auto* queue = g_render_ctx->GetGraphicCtx()->queue[m_queue];
const auto& queue = g_render_ctx->GetGraphicCtx()->queues[m_queue];
auto result = vkQueueSubmit(queue, 1, &submit_info, fence);
if (queue.mutex != nullptr)
{
queue.mutex->Lock();
}
auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
if (queue.mutex != nullptr)
{
queue.mutex->Lock();
}
m_execute = true;

View File

@ -514,9 +514,9 @@ void CommandProcessor::BufferInit()
{
EXIT_IF(buf != nullptr);
buf = new CommandBuffer;
buf = new CommandBuffer(m_queue);
buf->SetParent(this);
buf->SetQueue(m_queue);
// buf->SetQueue(m_queue);
}
m_current_buffer = 0;

View File

@ -333,8 +333,8 @@ void UtilFillImage(GraphicContext* ctx, VulkanImage* dst_image, const void* src_
std::memcpy(data, src_data, size);
VulkanUnmapMemory(ctx, &staging_buffer.memory);
CommandBuffer buffer;
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
CommandBuffer buffer(GraphicContext::QUEUE_UTIL);
// buffer.SetQueue(GraphicContext::QUEUE_UTIL);
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());
@ -360,8 +360,8 @@ void UtilFillBuffer(GraphicContext* ctx, void* dst_data, uint64_t size, uint32_t
staging_buffer.memory.property = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
VulkanCreateBuffer(ctx, size, &staging_buffer);
CommandBuffer buffer;
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
CommandBuffer buffer(GraphicContext::QUEUE_UTIL);
// buffer.SetQueue(GraphicContext::QUEUE_UTIL);
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());
@ -381,8 +381,8 @@ void UtilFillBuffer(GraphicContext* ctx, void* dst_data, uint64_t size, uint32_t
void UtilSetDepthLayoutOptimal(DepthStencilVulkanImage* image)
{
CommandBuffer buffer;
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
CommandBuffer buffer(GraphicContext::QUEUE_UTIL);
// buffer.SetQueue(GraphicContext::QUEUE_UTIL);
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());
@ -406,8 +406,8 @@ void UtilSetDepthLayoutOptimal(DepthStencilVulkanImage* image)
void UtilSetImageLayoutOptimal(VulkanImage* image)
{
CommandBuffer buffer;
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
CommandBuffer buffer(GraphicContext::QUEUE_UTIL);
// buffer.SetQueue(GraphicContext::QUEUE_UTIL);
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());
@ -440,8 +440,8 @@ void UtilFillImage(GraphicContext* ctx, VulkanImage* image, const void* src_data
std::memcpy(data, src_data, size);
VulkanUnmapMemory(ctx, &staging_buffer.memory);
CommandBuffer buffer;
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
CommandBuffer buffer(GraphicContext::QUEUE_UTIL);
// buffer.SetQueue(GraphicContext::QUEUE_UTIL);
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());
@ -459,8 +459,8 @@ void UtilFillImage(GraphicContext* ctx, const Vector<ImageImageCopy>& regions, V
EXIT_IF(ctx == nullptr);
EXIT_IF(dst_image == nullptr);
CommandBuffer buffer;
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
CommandBuffer buffer(GraphicContext::QUEUE_UTIL);
// buffer.SetQueue(GraphicContext::QUEUE_UTIL);
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());
@ -478,8 +478,8 @@ void UtilCopyBuffer(VulkanBuffer* src_buffer, VulkanBuffer* dst_buffer, uint64_t
EXIT_IF(dst_buffer == nullptr);
EXIT_IF(dst_buffer->buffer == nullptr);
CommandBuffer buffer;
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
CommandBuffer buffer(GraphicContext::QUEUE_UTIL);
// buffer.SetQueue(GraphicContext::QUEUE_UTIL);
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());

View File

@ -1302,13 +1302,153 @@ static bool CheckFormat(VkPhysicalDevice device, VkFormat format, bool tile, VkF
return false;
}
struct QueueInfo
{
uint32_t family = 0;
uint32_t index = 0;
bool graphics = false;
bool compute = false;
bool transfer = false;
bool present = false;
};
struct VulkanQueues
{
uint32_t family_count = 0;
Vector<uint32_t> family_used;
Vector<QueueInfo> available;
Vector<QueueInfo> graphics;
Vector<QueueInfo> compute;
Vector<QueueInfo> transfer;
Vector<QueueInfo> present;
};
static void VulkanDumpQueues(const VulkanQueues& qs)
{
printf("Queues selected:\n");
printf("\t family_count = %u\n", qs.family_count);
Core::StringList nums;
for (auto u: qs.family_used)
{
nums.Add(String::FromPrintf("%u", u));
}
printf("\t family_used = [%s]\n", nums.Concat(U", ").C_Str());
printf("\t graphics:\n");
for (const auto& q: qs.graphics)
{
printf("\t\t family = %u, index = %u\n", q.family, q.index);
}
printf("\t compute:\n");
for (const auto& q: qs.compute)
{
printf("\t\t family = %u, index = %u\n", q.family, q.index);
}
printf("\t transfer:\n");
for (const auto& q: qs.transfer)
{
printf("\t\t family = %u, index = %u\n", q.family, q.index);
}
printf("\t present:\n");
for (const auto& q: qs.present)
{
printf("\t\t family = %u, index = %u\n", q.family, q.index);
}
}
static VulkanQueues VulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR surface, uint32_t graphics_num, uint32_t compute_num,
uint32_t transfer_num, uint32_t present_num)
{
EXIT_IF(device == nullptr);
EXIT_IF(surface == nullptr);
VulkanQueues qs;
uint32_t queue_family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, nullptr);
Vector<VkQueueFamilyProperties> queue_families(queue_family_count);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families.GetData());
qs.family_count = queue_family_count;
uint32_t family = 0;
for (auto& f: queue_families)
{
VkBool32 presentation_supported = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(device, family, surface, &presentation_supported);
printf("\tqueue family: %s [count = %u], [present = %s]\n", string_VkQueueFlags(f.queueFlags).c_str(), f.queueCount,
(presentation_supported == VK_TRUE ? "true" : "false"));
for (uint32_t i = 0; i < f.queueCount; i++)
{
QueueInfo info;
info.family = family;
info.index = i;
info.graphics = (f.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0;
info.compute = (f.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0;
info.transfer = (f.queueFlags & VK_QUEUE_TRANSFER_BIT) != 0;
info.present = (presentation_supported == VK_TRUE);
qs.available.Add(info);
}
qs.family_used.Add(0);
family++;
}
for (uint32_t i = 0; i < graphics_num; i++)
{
if (auto index = qs.available.Find(true, [](auto& q, auto& b) { return q.graphics == b; }); qs.available.IndexValid(index))
{
qs.family_used[qs.available.At(index).family]++;
qs.graphics.Add(qs.available.At(index));
qs.available.RemoveAt(index);
}
}
for (uint32_t i = 0; i < compute_num; i++)
{
if (auto index = qs.available.Find(true, [](auto& q, auto& b) { return q.compute == b; }); qs.available.IndexValid(index))
{
qs.family_used[qs.available.At(index).family]++;
qs.compute.Add(qs.available.At(index));
qs.available.RemoveAt(index);
}
}
for (uint32_t i = 0; i < transfer_num; i++)
{
if (auto index = qs.available.Find(true, [](auto& q, auto& b) { return q.transfer == b; }); qs.available.IndexValid(index))
{
qs.family_used[qs.available.At(index).family]++;
qs.transfer.Add(qs.available.At(index));
qs.available.RemoveAt(index);
}
}
for (uint32_t i = 0; i < present_num; i++)
{
if (auto index = qs.available.Find(true, [](auto& q, auto& b) { return q.present == b; }); qs.available.IndexValid(index))
{
qs.family_used[qs.available.At(index).family]++;
qs.present.Add(qs.available.At(index));
qs.available.RemoveAt(index);
}
}
return qs;
}
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface, VkQueueFlags queue_family, uint32_t queue_count,
const Vector<const char*>& device_extensions,
SurfaceCapabilities* r /*, uint32_t image_count*/)
static void VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceKHR surface, const Vector<const char*>& device_extensions,
SurfaceCapabilities* out_capabilities, VkPhysicalDevice* out_device, VulkanQueues* out_queues)
{
EXIT_IF(instance == nullptr);
EXIT_IF(surface == nullptr);
EXIT_IF(out_capabilities == nullptr);
EXIT_IF(out_device == nullptr);
EXIT_IF(out_queues == nullptr);
uint32_t devices_count = 0;
vkEnumeratePhysicalDevices(instance, &devices_count, nullptr);
@ -1319,10 +1459,11 @@ static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceK
vkEnumeratePhysicalDevices(instance, &devices_count, devices.GetData());
VkPhysicalDevice best_device = nullptr;
VulkanQueues best_queues;
for (const auto& device: devices)
{
bool skip_device = true;
bool skip_device = false;
VkPhysicalDeviceProperties device_properties {};
VkPhysicalDeviceFeatures2 device_features2 {};
@ -1339,35 +1480,21 @@ static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceK
printf("Vulkan device: %s\n", device_properties.deviceName);
uint32_t queue_family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, nullptr);
auto qs = VulkanFindQueues(device, surface, GraphicContext::QUEUE_GFX_NUM, GraphicContext::QUEUE_COMPUTE_NUM,
GraphicContext::QUEUE_UTIL_NUM, GraphicContext::QUEUE_PRESENT_NUM);
Vector<VkQueueFamilyProperties> queue_families(queue_family_count);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families.GetData());
VulkanDumpQueues(qs);
for (auto& f: queue_families)
if (qs.graphics.Size() != GraphicContext::QUEUE_GFX_NUM ||
!(qs.compute.Size() >= 1 && qs.compute.Size() <= GraphicContext::QUEUE_COMPUTE_NUM) ||
qs.transfer.Size() != GraphicContext::QUEUE_UTIL_NUM || qs.present.Size() != GraphicContext::QUEUE_PRESENT_NUM)
{
printf("\tqueue family: %s [count = %u]\n", string_VkQueueFlags(f.queueFlags).c_str(), f.queueCount);
}
Vector<uint32_t> indexes;
queue_families.FindAll(
queue_family, [queue_count](auto f, auto bit) { return (f.queueFlags & bit) != 0 && f.queueCount >= queue_count; }, &indexes);
for (auto index: indexes)
{
VkBool32 presentation_supported = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(device, index, surface, &presentation_supported);
if (presentation_supported == VK_TRUE)
{
skip_device = false;
break;
}
printf("Not enough queues\n");
skip_device = true;
}
if (color_write_ext.colorWriteEnable != VK_TRUE)
{
printf("colorWriteEnable is not supported\n");
skip_device = true;
}
@ -1420,9 +1547,9 @@ static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceK
if (!skip_device)
{
VulkanGetSurfaceCapabilities(device, surface, r);
VulkanGetSurfaceCapabilities(device, surface, out_capabilities);
if ((r->capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0)
if ((out_capabilities->capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0)
{
printf("Surface cannot be destination of blit\n");
skip_device = true;
@ -1530,69 +1657,48 @@ static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceK
continue;
}
if (best_device == nullptr)
{
best_device = device;
}
if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
if (best_device == nullptr || device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
{
best_device = device;
best_queues = qs;
}
}
return best_device;
*out_device = best_device;
*out_queues = best_queues;
}
static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VulkanExtensions* r,
VkQueueFlags queue_family, uint32_t queue_count, uint32_t* queue_family_index,
const Vector<const char*>& device_extensions)
const VulkanQueues& queues, const Vector<const char*>& device_extensions)
{
EXIT_IF(physical_device == nullptr);
EXIT_IF(r == nullptr);
EXIT_IF(queue_family_index == nullptr);
EXIT_IF(surface == nullptr);
Vector<float> queue_priority(queue_count);
for (auto& f: queue_priority)
Vector<VkDeviceQueueCreateInfo> queue_create_info(queues.family_count);
Vector<Vector<float>> queue_priority(queues.family_count);
uint32_t queue_create_info_num = 0;
for (uint32_t i = 0; i < queues.family_count; i++)
{
f = 1.0f;
}
uint32_t queue_family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, nullptr);
Vector<VkQueueFamilyProperties> queue_families(queue_family_count);
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, queue_families.GetData());
Vector<uint32_t> indexes;
queue_families.FindAll(
queue_family, [queue_count](auto f, auto bit) { return (f.queueFlags & bit) != 0 && f.queueCount >= queue_count; }, &indexes);
*queue_family_index = queue_families.Size() + 1;
for (auto index: indexes)
{
VkBool32 presentation_supported = VK_FALSE;
vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, index, surface, &presentation_supported);
if (presentation_supported == VK_TRUE)
if (queues.family_used[i] != 0)
{
*queue_family_index = index;
break;
for (uint32_t pi = 0; pi < queues.family_used[i]; pi++)
{
queue_priority[queue_create_info_num].Add(1.0f);
}
queue_create_info[queue_create_info_num].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info[queue_create_info_num].pNext = nullptr;
queue_create_info[queue_create_info_num].flags = 0;
queue_create_info[queue_create_info_num].queueFamilyIndex = i;
queue_create_info[queue_create_info_num].queueCount = queues.family_used[i];
queue_create_info[queue_create_info_num].pQueuePriorities = queue_priority[queue_create_info_num].GetDataConst();
queue_create_info_num++;
}
}
EXIT_IF(!queue_families.IndexValid(*queue_family_index));
VkDeviceQueueCreateInfo queue_create_info {};
queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info.pNext = nullptr;
queue_create_info.flags = 0;
queue_create_info.queueFamilyIndex = *queue_family_index;
queue_create_info.queueCount = queue_count;
queue_create_info.pQueuePriorities = queue_priority.GetDataConst();
VkPhysicalDeviceFeatures device_features {};
device_features.fragmentStoresAndAtomics = VK_TRUE;
device_features.samplerAnisotropy = VK_TRUE;
@ -1607,8 +1713,8 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
create_info.pNext = &color_write_ext;
create_info.flags = 0;
create_info.pQueueCreateInfos = &queue_create_info;
create_info.queueCreateInfoCount = 1;
create_info.pQueueCreateInfos = queue_create_info.GetDataConst();
create_info.queueCreateInfoCount = queue_create_info_num;
create_info.enabledLayerCount = (r->enable_validation_layers ? r->required_layers.Size() : 0);
create_info.ppEnabledLayerNames = (r->enable_validation_layers ? r->required_layers.GetDataConst() : nullptr);
create_info.enabledExtensionCount = device_extensions.Size();
@ -1902,17 +2008,36 @@ static VKAPI_ATTR VkResult VKAPI_CALL VulkanCreateDebugUtilsMessengerEXT(VkInsta
return swapchain;
}
static void VulkanCreateQueues(GraphicContext* ctx)
static void VulkanCreateQueues(GraphicContext* ctx, const VulkanQueues& queues)
{
EXIT_IF(ctx == nullptr);
EXIT_IF(ctx->device == nullptr);
EXIT_IF(ctx->queue_family_index == static_cast<uint32_t>(-1));
EXIT_IF(queues.graphics.Size() != 1);
EXIT_IF(queues.transfer.Size() != 1);
EXIT_IF(queues.present.Size() != 1);
EXIT_IF(!(queues.compute.Size() >= 1 && queues.compute.Size() <= GraphicContext::QUEUE_COMPUTE_NUM));
for (int i = 0; i < GraphicContext::QUEUES_NUM; i++)
auto get_queue = [ctx](int id, const QueueInfo& info, bool with_mutex = false)
{
EXIT_IF(ctx->queue[i] != nullptr);
vkGetDeviceQueue(ctx->device, ctx->queue_family_index, i, &ctx->queue[i]);
EXIT_NOT_IMPLEMENTED(ctx->queue[i] == nullptr);
ctx->queues[id].family = info.family;
ctx->queues[id].index = info.index;
EXIT_IF(ctx->queues[id].vk_queue != nullptr);
vkGetDeviceQueue(ctx->device, ctx->queues[id].family, ctx->queues[id].index, &ctx->queues[id].vk_queue);
EXIT_NOT_IMPLEMENTED(ctx->queues[id].vk_queue == nullptr);
if (with_mutex)
{
ctx->queues[id].mutex = new Core::Mutex;
}
};
get_queue(GraphicContext::QUEUE_GFX, queues.graphics.At(0));
get_queue(GraphicContext::QUEUE_UTIL, queues.transfer.At(0));
get_queue(GraphicContext::QUEUE_PRESENT, queues.present.At(0));
for (int id = 0; id < GraphicContext::QUEUE_COMPUTE_NUM; id++)
{
bool with_mutex = (GraphicContext::QUEUE_COMPUTE_NUM == queues.compute.Size());
get_queue(GraphicContext::QUEUE_COMPUTE_START + id, queues.compute.At(id % queues.compute.Size()), with_mutex);
}
}
@ -2063,9 +2188,11 @@ static void VulkanCreate(WindowContext* ctx)
ctx->surface_capabilities = new SurfaceCapabilities {};
ctx->graphic_ctx.physical_device =
VulkanFindPhysicalDevice(ctx->graphic_ctx.instance, ctx->surface, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
GraphicContext::QUEUES_NUM, device_extensions, ctx->surface_capabilities);
VulkanQueues queues;
VulkanFindPhysicalDevice(ctx->graphic_ctx.instance, ctx->surface, device_extensions, ctx->surface_capabilities,
&ctx->graphic_ctx.physical_device, &queues);
if (ctx->graphic_ctx.physical_device == nullptr)
{
EXIT("Could not find suitable device");
@ -2079,15 +2206,13 @@ static void VulkanCreate(WindowContext* ctx)
memcpy(ctx->device_name, device_properties.deviceName, sizeof(ctx->device_name));
memcpy(ctx->processor_name, Loader::GetSystemInfo().ProcessorName.C_Str(), sizeof(ctx->processor_name));
ctx->graphic_ctx.device =
VulkanCreateDevice(ctx->graphic_ctx.physical_device, ctx->surface, &r, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
GraphicContext::QUEUES_NUM, &ctx->graphic_ctx.queue_family_index, device_extensions);
ctx->graphic_ctx.device = VulkanCreateDevice(ctx->graphic_ctx.physical_device, ctx->surface, &r, queues, device_extensions);
if (ctx->graphic_ctx.device == nullptr)
{
EXIT("Could not create device");
}
VulkanCreateQueues(&ctx->graphic_ctx);
VulkanCreateQueues(&ctx->graphic_ctx, queues);
ctx->swapchain = VulkanCreateSwapchain(&ctx->graphic_ctx, 2);
}
@ -2238,8 +2363,8 @@ void WindowDrawBuffer(VideoOutVulkanImage* image)
EXIT_IF(blt_src_image == nullptr);
EXIT_IF(blt_dst_image == nullptr);
CommandBuffer buffer;
buffer.SetQueue(GraphicContext::QUEUE_PRESENT);
CommandBuffer buffer(GraphicContext::QUEUE_PRESENT);
// buffer.SetQueue(GraphicContext::QUEUE_PRESENT);
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());
@ -2280,7 +2405,11 @@ void WindowDrawBuffer(VideoOutVulkanImage* image)
present.waitSemaphoreCount = 1;
present.pResults = nullptr;
result = vkQueuePresentKHR(g_window_ctx->graphic_ctx.queue[GraphicContext::QUEUE_PRESENT], &present);
const auto& queue = g_window_ctx->graphic_ctx.queues[GraphicContext::QUEUE_PRESENT];
EXIT_IF(queue.mutex != nullptr);
result = vkQueuePresentKHR(queue.vk_queue, &present);
EXIT_NOT_IMPLEMENTED(result != VK_SUCCESS);
WindowUpdateTitle();