vulkan stuff

This commit is contained in:
izzy2lost
2026-03-21 01:07:13 -04:00
parent 486d2c52a0
commit c989586690
2 changed files with 230 additions and 2 deletions
+70
View File
@@ -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;
+160 -2
View File
@@ -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
}