mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
vulkan stuff
This commit is contained in:
@@ -22,6 +22,9 @@
|
||||
#include "renderer.h"
|
||||
#include "hw/xbox/nv2a/pgraph/prim_rewrite.h"
|
||||
#include <math.h>
|
||||
#ifdef __aarch64__
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
#include <SDL.h>
|
||||
#include <android/log.h>
|
||||
@@ -2032,6 +2035,63 @@ static VertexBufferRemap remap_unaligned_attributes(PGRAPHState *pg,
|
||||
return remap;
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
static inline bool copy_remapped_attribute_arm64(uint8_t *dst,
|
||||
const uint8_t *src,
|
||||
VkDeviceSize old_stride,
|
||||
VkDeviceSize new_stride,
|
||||
uint32_t num_vertices)
|
||||
{
|
||||
switch (new_stride) {
|
||||
case 4:
|
||||
for (uint32_t vertex_id = 0; vertex_id < num_vertices; vertex_id++) {
|
||||
uint32_t word;
|
||||
|
||||
memcpy(&word, src, sizeof(word));
|
||||
memcpy(dst, &word, sizeof(word));
|
||||
|
||||
dst += new_stride;
|
||||
src += old_stride;
|
||||
}
|
||||
return true;
|
||||
|
||||
case 8:
|
||||
for (uint32_t vertex_id = 0; vertex_id < num_vertices; vertex_id++) {
|
||||
vst1_u8(dst, vld1_u8(src));
|
||||
|
||||
dst += new_stride;
|
||||
src += old_stride;
|
||||
}
|
||||
return true;
|
||||
|
||||
case 12:
|
||||
for (uint32_t vertex_id = 0; vertex_id < num_vertices; vertex_id++) {
|
||||
uint32_t tail_word;
|
||||
|
||||
vst1_u8(dst, vld1_u8(src));
|
||||
memcpy(&tail_word, src + 8, sizeof(tail_word));
|
||||
memcpy(dst + 8, &tail_word, sizeof(tail_word));
|
||||
|
||||
dst += new_stride;
|
||||
src += old_stride;
|
||||
}
|
||||
return true;
|
||||
|
||||
case 16:
|
||||
for (uint32_t vertex_id = 0; vertex_id < num_vertices; vertex_id++) {
|
||||
vst1q_u8(dst, vld1q_u8(src));
|
||||
|
||||
dst += new_stride;
|
||||
src += old_stride;
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void copy_remapped_attributes_to_inline_buffer(PGRAPHState *pg,
|
||||
VertexBufferRemap remap,
|
||||
uint32_t start_vertex,
|
||||
@@ -2066,6 +2126,16 @@ static void copy_remapped_attributes_to_inline_buffer(PGRAPHState *pg,
|
||||
uint8_t *out_ptr = buffer->mapped + attr_buffer_offset;
|
||||
uint8_t *in_ptr = d->vram_ptr + r->vertex_attribute_offsets[attr_id];
|
||||
|
||||
#ifdef __aarch64__
|
||||
if (copy_remapped_attribute_arm64(out_ptr, in_ptr,
|
||||
remap.map[attr_id].old_stride,
|
||||
remap.map[attr_id].new_stride,
|
||||
num_vertices)) {
|
||||
r->vertex_attribute_offsets[attr_id] = attr_buffer_offset;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int vertex_id = 0; vertex_id < num_vertices; vertex_id++) {
|
||||
memcpy(out_ptr, in_ptr, remap.map[attr_id].new_stride);
|
||||
out_ptr += remap.map[attr_id].new_stride;
|
||||
|
||||
@@ -384,6 +384,163 @@ static bool check_device_support_required_extensions(VkPhysicalDevice device)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void report_device_incompatibility(VkPhysicalDevice device,
|
||||
const char *reason)
|
||||
{
|
||||
VkPhysicalDeviceProperties props;
|
||||
vkGetPhysicalDeviceProperties(device, &props);
|
||||
|
||||
fprintf(stderr, "Vulkan device rejected (%s): %s\n", props.deviceName,
|
||||
reason);
|
||||
#ifdef __ANDROID__
|
||||
__android_log_print(ANDROID_LOG_WARN, "xemu-android",
|
||||
"Vulkan device rejected (%s): %s", props.deviceName,
|
||||
reason);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool format_already_checked(const VkFormat *formats, size_t count,
|
||||
VkFormat format)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (formats[i] == format) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool check_format_supports_features(VkPhysicalDevice device,
|
||||
VkFormat format,
|
||||
VkFormatFeatureFlags features)
|
||||
{
|
||||
VkFormatProperties props;
|
||||
vkGetPhysicalDeviceFormatProperties(device, format, &props);
|
||||
|
||||
return (props.optimalTilingFeatures & features) == features;
|
||||
}
|
||||
|
||||
static bool check_image_format_usage_supported(VkPhysicalDevice device,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags usage)
|
||||
{
|
||||
VkPhysicalDeviceImageFormatInfo2 info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
|
||||
.format = format,
|
||||
.type = VK_IMAGE_TYPE_2D,
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.usage = usage,
|
||||
};
|
||||
VkImageFormatProperties2 props = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
|
||||
};
|
||||
|
||||
return vkGetPhysicalDeviceImageFormatProperties2(device, &info, &props) ==
|
||||
VK_SUCCESS;
|
||||
}
|
||||
|
||||
static bool check_texture_formats_supported(VkPhysicalDevice device)
|
||||
{
|
||||
VkFormat checked_formats[ARRAY_SIZE(kelvin_color_format_vk_map)];
|
||||
size_t num_checked_formats = 0;
|
||||
const VkImageUsageFlags usage =
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
|
||||
memset(checked_formats, 0, sizeof(checked_formats));
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(kelvin_color_format_vk_map); i++) {
|
||||
VkFormat format = kelvin_color_format_vk_map[i].vk_format;
|
||||
|
||||
if (format == VK_FORMAT_UNDEFINED ||
|
||||
format_already_checked(checked_formats, num_checked_formats,
|
||||
format)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
checked_formats[num_checked_formats++] = format;
|
||||
|
||||
if (!check_format_supports_features(device, format,
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ||
|
||||
!check_image_format_usage_supported(device, format, usage)) {
|
||||
char reason[160];
|
||||
|
||||
snprintf(reason, sizeof(reason),
|
||||
"sampled texture uploads need VkFormat %d to support "
|
||||
"optimal sampled images and transfer-dst usage",
|
||||
format);
|
||||
report_device_incompatibility(device, reason);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool check_surface_format_supported(VkPhysicalDevice device,
|
||||
const SurfaceFormatInfo *format)
|
||||
{
|
||||
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
format->usage;
|
||||
|
||||
return check_image_format_usage_supported(device, format->vk_format, usage) &&
|
||||
check_format_supports_features(device, format->vk_format,
|
||||
VK_FORMAT_FEATURE_BLIT_SRC_BIT |
|
||||
VK_FORMAT_FEATURE_BLIT_DST_BIT);
|
||||
}
|
||||
|
||||
static bool check_surface_formats_supported(VkPhysicalDevice device)
|
||||
{
|
||||
VkFormat checked_formats[ARRAY_SIZE(kelvin_surface_color_format_vk_map)];
|
||||
size_t num_checked_formats = 0;
|
||||
|
||||
memset(checked_formats, 0, sizeof(checked_formats));
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(kelvin_surface_color_format_vk_map); i++) {
|
||||
const SurfaceFormatInfo *format = &kelvin_surface_color_format_vk_map[i];
|
||||
|
||||
if (!format->host_bytes_per_pixel ||
|
||||
format_already_checked(checked_formats, num_checked_formats,
|
||||
format->vk_format)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
checked_formats[num_checked_formats++] = format->vk_format;
|
||||
|
||||
if (!check_surface_format_supported(device, format)) {
|
||||
char reason[192];
|
||||
|
||||
snprintf(reason, sizeof(reason),
|
||||
"surface format VkFormat %d needs sampled, transfer, "
|
||||
"attachment, and blit support",
|
||||
format->vk_format);
|
||||
report_device_incompatibility(device, reason);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!check_surface_format_supported(device, &zeta_d16)) {
|
||||
report_device_incompatibility(
|
||||
device,
|
||||
"Z16 surfaces need sampled, transfer, attachment, and blit support");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_surface_format_supported(device, &zeta_d24_unorm_s8_uint) &&
|
||||
!check_surface_format_supported(device, &zeta_d32_sfloat_s8_uint)) {
|
||||
report_device_incompatibility(
|
||||
device,
|
||||
"Z24S8 surfaces need either D24_UNORM_S8_UINT or "
|
||||
"D32_SFLOAT_S8_UINT with sampled, transfer, attachment, and blit "
|
||||
"support");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_device_compatible(VkPhysicalDevice device)
|
||||
{
|
||||
VkPhysicalDeviceProperties props;
|
||||
@@ -395,8 +552,9 @@ static bool is_device_compatible(VkPhysicalDevice device)
|
||||
QueueFamilyIndices indices = pgraph_vk_find_queue_families(device);
|
||||
|
||||
return is_queue_family_indicies_complete(indices) &&
|
||||
check_device_support_required_extensions(device);
|
||||
// FIXME: Check formats
|
||||
check_device_support_required_extensions(device) &&
|
||||
check_texture_formats_supported(device) &&
|
||||
check_surface_formats_supported(device);
|
||||
// FIXME: Check vram
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user