more work on graphics . tiles are not yet supported

This commit is contained in:
georgemoralis 2023-09-27 22:47:53 +03:00
parent abe6d39295
commit 05fdea61fc
7 changed files with 242 additions and 5 deletions

View File

@ -3,11 +3,22 @@
#include <Util/log.h> #include <Util/log.h>
#include "debug.h" #include "debug.h"
#include <vulkan_util.h>
constexpr bool log_file_videoOutBuffer = true; // disable it to disable logging constexpr bool log_file_videoOutBuffer = true; // disable it to disable logging
static void update_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, void* obj, const u64* virtual_addr, const u64* size, static void update_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, void* obj, const u64* virtual_addr, const u64* size,
int virtual_addr_num) {} int virtual_addr_num) {
auto pitch = params[GPU::VideoOutBufferObj::PITCH_PARAM];
auto* vk_obj = static_cast<HLE::Libs::Graphics::VideoOutVulkanImage*>(obj);
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED;
Graphics::Vulkan::vulkanFillImage(ctx, vk_obj, reinterpret_cast<void*>(*virtual_addr), *size, pitch,
static_cast<uint64_t>(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
}
static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* virtual_addr, const u64* size, int virtual_addr_num, static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* virtual_addr, const u64* size, int virtual_addr_num,
HLE::Libs::Graphics::VulkanMemory* mem) { HLE::Libs::Graphics::VulkanMemory* mem) {

View File

@ -2,6 +2,7 @@
#include <types.h> #include <types.h>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include "Lib/Threads.h" #include "Lib/Threads.h"
namespace HLE::Libs::Graphics { namespace HLE::Libs::Graphics {
@ -32,7 +33,7 @@ struct GraphicCtx {
VulkanQueueInfo queues[11]; // VULKAN_QUEUES_NUM VulkanQueueInfo queues[11]; // VULKAN_QUEUES_NUM
}; };
enum class VulkanImageType { Unknown, VideoOut}; enum class VulkanImageType { Unknown, VideoOut };
struct VulkanMemory { struct VulkanMemory {
VkMemoryRequirements requirements = {}; VkMemoryRequirements requirements = {};
@ -43,6 +44,11 @@ struct VulkanMemory {
u64 unique_id = 0; u64 unique_id = 0;
}; };
struct VulkanBuffer {
VkBuffer buffer = nullptr;
VulkanMemory memory;
VkBufferUsageFlags usage = 0;
};
struct VulkanImage { struct VulkanImage {
static constexpr int VIEW_MAX = 4; static constexpr int VIEW_MAX = 4;
static constexpr int VIEW_DEFAULT = 0; static constexpr int VIEW_DEFAULT = 0;

View File

@ -109,6 +109,41 @@ void GPU::CommandBuffer::executeWithSemaphore() {
std::exit(0); std::exit(0);
} }
} }
void GPU::CommandBuffer::execute() {
auto* buffer = m_pool->buffers[m_index];
auto* fence = m_pool->fences[m_index];
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = nullptr;
submit_info.waitSemaphoreCount = 0;
submit_info.pWaitSemaphores = nullptr;
submit_info.pWaitDstStageMask = nullptr;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &buffer;
submit_info.signalSemaphoreCount = 0;
submit_info.pSignalSemaphores = nullptr;
auto* render_ctx = Singleton<RenderCtx>::Instance();
const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue];
if (queue.mutex != nullptr) {
queue.mutex->LockMutex();
}
auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
if (queue.mutex != nullptr) {
queue.mutex->UnlockMutex();
}
m_execute = true;
if (result != VK_SUCCESS) {
printf("vkQueueSubmit failed\n");
std::exit(0);
}
}
void GPU::CommandPool::createPool(int id) { void GPU::CommandPool::createPool(int id) {
auto* render_ctx = Singleton<RenderCtx>::Instance(); auto* render_ctx = Singleton<RenderCtx>::Instance();
auto* ctx = render_ctx->getGraphicCtx(); auto* ctx = render_ctx->getGraphicCtx();
@ -195,4 +230,3 @@ void GPU::CommandPool::deleteAllPool() {
} }
} }
} }

View File

@ -31,6 +31,7 @@ class CommandBuffer {
void begin() const; void begin() const;
void end() const; void end() const;
void executeWithSemaphore(); void executeWithSemaphore();
void execute();
u32 getIndex() const { return m_index; } u32 getIndex() const { return m_index; }
HLE::Libs::Graphics::VulkanCommandPool* getPool() { return m_pool; } HLE::Libs::Graphics::VulkanCommandPool* getPool() { return m_pool; }
private: private:

View File

@ -150,7 +150,7 @@ void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image) {
buffer.begin(); buffer.begin();
//UtilBlitImage(&buffer, blt_src_image, blt_dst_image); Graphics::Vulkan::vulkanBlitImage(&buffer, blt_src_image, blt_dst_image);
VkImageMemoryBarrier pre_present_barrier{}; VkImageMemoryBarrier pre_present_barrier{};
pre_present_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; pre_present_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;

View File

@ -1,5 +1,6 @@
#include "vulkan_util.h" #include "vulkan_util.h"
#include <Core/PS4/GPU/gpu_memory.h>
#include <SDL_vulkan.h> #include <SDL_vulkan.h>
#include <Util/Singleton.h> #include <Util/Singleton.h>
#include <Util/log.h> #include <Util/log.h>
@ -181,6 +182,7 @@ Emulator::VulkanSwapchain* Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Gr
return s; return s;
} }
void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues) { void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues) {
auto get_queue = [ctx](int id, const Emulator::VulkanQueueInfo& info, bool with_mutex = false) { auto get_queue = [ctx](int id, const Emulator::VulkanQueueInfo& info, bool with_mutex = false) {
ctx->queues[id].family = info.family; ctx->queues[id].family = info.family;
@ -425,3 +427,178 @@ void Graphics::Vulkan::vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_de
} }
} }
} }
static void set_image_layout(VkCommandBuffer buffer, HLE::Libs::Graphics::VulkanImage* dst_image, uint32_t base_level, uint32_t levels,
VkImageAspectFlags aspect_mask, VkImageLayout old_image_layout, VkImageLayout new_image_layout) {
VkImageMemoryBarrier imageMemoryBarrier{};
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imageMemoryBarrier.pNext = nullptr;
imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = 0;
imageMemoryBarrier.oldLayout = old_image_layout;
imageMemoryBarrier.newLayout = new_image_layout;
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.image = dst_image->image;
imageMemoryBarrier.subresourceRange.aspectMask = aspect_mask;
imageMemoryBarrier.subresourceRange.baseMipLevel = base_level;
imageMemoryBarrier.subresourceRange.levelCount = levels;
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
imageMemoryBarrier.subresourceRange.layerCount = 1;
if (old_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
imageMemoryBarrier.srcAccessMask = 0;
}
if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
imageMemoryBarrier.dstAccessMask = 0;
}
if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
imageMemoryBarrier.dstAccessMask = 0;
}
if (old_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
imageMemoryBarrier.srcAccessMask = 0;
}
if (old_image_layout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
}
if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
imageMemoryBarrier.srcAccessMask = 0;
imageMemoryBarrier.dstAccessMask = 0;
}
if (new_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
imageMemoryBarrier.dstAccessMask = 0;
}
if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
imageMemoryBarrier.dstAccessMask = 0;
}
VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
vkCmdPipelineBarrier(buffer, src_stages, dest_stages, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
dst_image->layout = new_image_layout;
}
void Graphics::Vulkan::vulkanBlitImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanImage* src_image,
Emulator::VulkanSwapchain* dst_swapchain) {
auto* vk_buffer = buffer->getPool()->buffers[buffer->getIndex()];
HLE::Libs::Graphics::VulkanImage swapchain_image(HLE::Libs::Graphics::VulkanImageType::Unknown);
swapchain_image.image = dst_swapchain->swapchain_images[dst_swapchain->current_index];
swapchain_image.layout = VK_IMAGE_LAYOUT_UNDEFINED;
set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
set_image_layout(vk_buffer, &swapchain_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkImageBlit region{};
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.srcSubresource.mipLevel = 0;
region.srcSubresource.baseArrayLayer = 0;
region.srcSubresource.layerCount = 1;
region.srcOffsets[0].x = 0;
region.srcOffsets[0].y = 0;
region.srcOffsets[0].z = 0;
region.srcOffsets[1].x = static_cast<int>(src_image->extent.width);
region.srcOffsets[1].y = static_cast<int>(src_image->extent.height);
region.srcOffsets[1].z = 1;
region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.dstSubresource.mipLevel = 0;
region.dstSubresource.baseArrayLayer = 0;
region.dstSubresource.layerCount = 1;
region.dstOffsets[0].x = 0;
region.dstOffsets[0].y = 0;
region.dstOffsets[0].z = 0;
region.dstOffsets[1].x = static_cast<int>(dst_swapchain->swapchain_extent.width);
region.dstOffsets[1].y = static_cast<int>(dst_swapchain->swapchain_extent.height);
region.dstOffsets[1].z = 1;
vkCmdBlitImage(vk_buffer, src_image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapchain_image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
&region, VK_FILTER_LINEAR);
set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
}
void Graphics::Vulkan::vulkanFillImage(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanImage* dst_image, const void* src_data,
u64 size, u32 src_pitch, u64 dst_layout) {
HLE::Libs::Graphics::VulkanBuffer staging_buffer{};
staging_buffer.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
staging_buffer.memory.property = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
vulkanCreateBuffer(ctx, size, &staging_buffer);
void* data = nullptr;
vkMapMemory(ctx->m_device, staging_buffer.memory.memory, staging_buffer.memory.offset, staging_buffer.memory.requirements.size, 0, &data);
std::memcpy(data, src_data, size);
vkUnmapMemory(ctx->m_device, staging_buffer.memory.memory);
GPU::CommandBuffer buffer(9);
buffer.begin();
vulkanBufferToImage(&buffer, &staging_buffer, src_pitch, dst_image, dst_layout);
buffer.end();
buffer.execute();
buffer.waitForFence();
vulkanDeleteBuffer(ctx, &staging_buffer);
}
void Graphics::Vulkan::vulkanBufferToImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanBuffer* src_buffer, u32 src_pitch,
HLE::Libs::Graphics::VulkanImage* dst_image, u64 dst_layout) {
auto* vk_buffer = buffer->getPool()->buffers[buffer->getIndex()];
set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkBufferImageCopy region{};
region.bufferOffset = 0;
region.bufferRowLength = (src_pitch != dst_image->extent.width ? src_pitch : 0);
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = {0, 0, 0};
region.imageExtent = {dst_image->extent.width, dst_image->extent.height, 1};
vkCmdCopyBufferToImage(vk_buffer, src_buffer->buffer, dst_image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
static_cast<VkImageLayout>(dst_layout));
}
void Graphics::Vulkan::vulkanCreateBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, u64 size, HLE::Libs::Graphics::VulkanBuffer* buffer) {
VkBufferCreateInfo buffer_info{};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = size;
buffer_info.usage = buffer->usage;
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
vkCreateBuffer(ctx->m_device, &buffer_info, nullptr, &buffer->buffer);
vkGetBufferMemoryRequirements(ctx->m_device, buffer->buffer, &buffer->memory.requirements);
bool allocated = GPU::vulkanAllocateMemory(ctx, &buffer->memory);
if (!allocated) {
printf("Can't allocate vulkan\n");
std::exit(0);
}
vkBindBufferMemory(ctx->m_device, buffer->buffer, buffer->memory.memory, buffer->memory.offset);
}
void Graphics::Vulkan::vulkanDeleteBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanBuffer* buffer) {
vkDestroyBuffer(ctx->m_device, buffer->buffer, nullptr);
vkFreeMemory(ctx->m_device, buffer->memory.memory, nullptr);
buffer->memory.memory = nullptr;
buffer->buffer = nullptr;
}

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <Core/PS4/HLE/Graphics/graphics_render.h>
#include <SDL.h> #include <SDL.h>
#include <src/video/khronos/vulkan/vulkan_core.h> #include <src/video/khronos/vulkan/vulkan_core.h>
@ -36,4 +37,11 @@ Emulator::VulkanQueues vulkanFindQueues(VkPhysicalDevice device, VkSurfaceKHR su
void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Emulator::VulkanSurfaceCapabilities* surfaceCap); void vulkanGetSurfaceCapabilities(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Emulator::VulkanSurfaceCapabilities* surfaceCap);
void vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues); void vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues);
Emulator::VulkanSwapchain* vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count); Emulator::VulkanSwapchain* vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count);
void vulkanBlitImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanImage* src_image, Emulator::VulkanSwapchain* dst_swapchain);
void vulkanFillImage(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanImage* dst_image, const void* src_data, u64 size, u32 src_pitch,
u64 dst_layout);
void vulkanBufferToImage(GPU::CommandBuffer* buffer, HLE::Libs::Graphics::VulkanBuffer* src_buffer, u32 src_pitch,
HLE::Libs::Graphics::VulkanImage* dst_image, u64 dst_layout);
void vulkanCreateBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, u64 size, HLE::Libs::Graphics::VulkanBuffer* buffer);
void vulkanDeleteBuffer(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanBuffer* buffer);
}; // namespace Graphics::Vulkan }; // namespace Graphics::Vulkan