blob: 17f7e3c76a4415d0a95965d379a74e1eda8603cb [file] [log] [blame]
// Copyright 2021 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 "target_requirements.h"
#include <stdio.h>
#include <string.h>
#include "common/macros.h"
#include "radix_sort/platforms/vk/radix_sort_vk.h"
#include "target.h"
#include "target_archive/target_archive.h"
//
//
//
struct radix_sort_vk_target
{
struct target_archive_header ar_header;
};
//
// RADIX_SORT TARGET REQUIREMENTS: VULKAN
//
bool
radix_sort_vk_target_get_requirements(radix_sort_vk_target_t const * target,
radix_sort_vk_target_requirements_t * requirements)
{
//
// Must not be NULL
//
if ((target == NULL) || (requirements == NULL))
{
#ifndef NDEBUG
fprintf(stderr, "Error: ((target == NULL) || (requirements == NULL))\n");
#endif
return false;
}
//
// Unmarshalling assumes dword alignment.
//
assert(alignof(struct radix_sort_vk_target_header) == 4);
//
// Verify target archive is valid archive
//
#ifndef RS_VK_DISABLE_VERIFY
if (target->ar_header.magic != TARGET_ARCHIVE_MAGIC)
{
#ifndef NDEBUG
fprintf(stderr, "Error: Missing magic -- Invalid target archive.\n");
#endif
return NULL;
}
#endif
//
// Get the target archive header
//
struct target_archive_header const * const ar_header = &target->ar_header;
struct target_archive_entry const * const ar_entries = ar_header->entries;
uint32_t const * const ar_data = ar_entries[ar_header->count - 1].data;
//
// Get the radix sort target header
//
struct radix_sort_vk_target_header const * rs_target_header;
// We assert `alignof(radix_sort_vk_target_header) == 4` (see above) so we can
// memcpy() pointers.
memcpy(&rs_target_header, &ar_data, sizeof(ar_data));
//
// Verify target is compatible with the library.
//
#ifndef RS_VK_DISABLE_VERIFY
if (rs_target_header->magic != RS_HEADER_MAGIC)
{
#ifndef NDEBUG
fprintf(stderr, "Error: Missing magic -- Invalid target archive for radix sort.\n");
#endif
return NULL;
}
#endif
//
//
//
bool is_ok = true;
//
// EXTENSIONS
//
{
//
// Compute number of required extensions
//
uint32_t ext_count = 0;
for (uint32_t ii = 0; ii < ARRAY_LENGTH_MACRO(rs_target_header->extensions.bitmap); ii++)
{
ext_count += __builtin_popcount(rs_target_header->extensions.bitmap[ii]);
}
if (requirements->ext_names == NULL)
{
requirements->ext_name_count = ext_count;
if (ext_count > 0)
{
is_ok = false;
}
}
else
{
if (requirements->ext_name_count < ext_count)
{
is_ok = false;
}
else
{
//
// FIXME(allanmac): This can be accelerated by exploiting
// the extension bitmap.
//
uint32_t ii = 0;
#define RS_VK_TARGET_EXTENSION_STRING(ext_) "VK_" STRINGIFY_MACRO(ext_)
#undef RS_VK_TARGET_EXTENSION
#define RS_VK_TARGET_EXTENSION(ext_) \
if (rs_target_header->extensions.named.ext_) \
{ \
requirements->ext_names[ii++] = RS_VK_TARGET_EXTENSION_STRING(ext_); \
}
RS_VK_TARGET_EXTENSIONS()
}
}
}
//
// Enable physical device features
//
if ((requirements->pdf == NULL) || (requirements->pdf11 == NULL) || (requirements->pdf12 == NULL))
{
is_ok = false;
}
else
{
#undef RS_VK_TARGET_FEATURE_VK10
#define RS_VK_TARGET_FEATURE_VK10(feature_) 1 +
#undef RS_VK_TARGET_FEATURE_VK11
#define RS_VK_TARGET_FEATURE_VK11(feature_) 1 +
#undef RS_VK_TARGET_FEATURE_VK12
#define RS_VK_TARGET_FEATURE_VK12(feature_) 1 +
//
// Don't create the variable if it's not used
//
#if (RS_VK_TARGET_FEATURES_VK10() 0)
VkPhysicalDeviceFeatures * const pdf = requirements->pdf;
#endif
#if (RS_VK_TARGET_FEATURES_VK11() 0)
VkPhysicalDeviceVulkan11Features * const pdf11 = requirements->pdf11;
#endif
#if (RS_VK_TARGET_FEATURES_VK12() 0)
VkPhysicalDeviceVulkan12Features * const pdf12 = requirements->pdf12;
#endif
//
// Let's always have this on during debug
//
#ifndef NDEBUG
pdf->robustBufferAccess = true;
#endif
//
// VULKAN 1.0
//
#undef RS_VK_TARGET_FEATURE_VK10
#define RS_VK_TARGET_FEATURE_VK10(feature_) \
if (rs_target_header->features.named.feature_) \
pdf->feature_ = true;
RS_VK_TARGET_FEATURES_VK10()
//
// VULKAN 1.1
//
#undef RS_VK_TARGET_FEATURE_VK11
#define RS_VK_TARGET_FEATURE_VK11(feature_) \
if (rs_target_header->features.named.feature_) \
pdf11->feature_ = true;
RS_VK_TARGET_FEATURES_VK11()
//
// VULKAN 1.2
//
#undef RS_VK_TARGET_FEATURE_VK12
#define RS_VK_TARGET_FEATURE_VK12(feature_) \
if (rs_target_header->features.named.feature_) \
pdf12->feature_ = true;
RS_VK_TARGET_FEATURES_VK12()
}
//
//
//
return is_ok;
}
//
//
//