more work on graphics . tiles are not yet supported
This commit is contained in:
parent
abe6d39295
commit
05fdea61fc
|
@ -3,11 +3,22 @@
|
|||
#include <Util/log.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include <vulkan_util.h>
|
||||
|
||||
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,
|
||||
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,
|
||||
HLE::Libs::Graphics::VulkanMemory* mem) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <types.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "Lib/Threads.h"
|
||||
|
||||
namespace HLE::Libs::Graphics {
|
||||
|
@ -43,6 +44,11 @@ struct VulkanMemory {
|
|||
u64 unique_id = 0;
|
||||
};
|
||||
|
||||
struct VulkanBuffer {
|
||||
VkBuffer buffer = nullptr;
|
||||
VulkanMemory memory;
|
||||
VkBufferUsageFlags usage = 0;
|
||||
};
|
||||
struct VulkanImage {
|
||||
static constexpr int VIEW_MAX = 4;
|
||||
static constexpr int VIEW_DEFAULT = 0;
|
||||
|
|
|
@ -109,6 +109,41 @@ void GPU::CommandBuffer::executeWithSemaphore() {
|
|||
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) {
|
||||
auto* render_ctx = Singleton<RenderCtx>::Instance();
|
||||
auto* ctx = render_ctx->getGraphicCtx();
|
||||
|
@ -195,4 +230,3 @@ void GPU::CommandPool::deleteAllPool() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ class CommandBuffer {
|
|||
void begin() const;
|
||||
void end() const;
|
||||
void executeWithSemaphore();
|
||||
void execute();
|
||||
u32 getIndex() const { return m_index; }
|
||||
HLE::Libs::Graphics::VulkanCommandPool* getPool() { return m_pool; }
|
||||
private:
|
||||
|
|
|
@ -150,7 +150,7 @@ void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image) {
|
|||
|
||||
buffer.begin();
|
||||
|
||||
//UtilBlitImage(&buffer, blt_src_image, blt_dst_image);
|
||||
Graphics::Vulkan::vulkanBlitImage(&buffer, blt_src_image, blt_dst_image);
|
||||
|
||||
VkImageMemoryBarrier pre_present_barrier{};
|
||||
pre_present_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "vulkan_util.h"
|
||||
|
||||
#include <Core/PS4/GPU/gpu_memory.h>
|
||||
#include <SDL_vulkan.h>
|
||||
#include <Util/Singleton.h>
|
||||
#include <Util/log.h>
|
||||
|
@ -181,6 +182,7 @@ Emulator::VulkanSwapchain* Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Gr
|
|||
|
||||
return s;
|
||||
}
|
||||
|
||||
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) {
|
||||
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,
|
||||
®ion, 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, ®ion);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#include <Core/PS4/HLE/Graphics/graphics_render.h>
|
||||
#include <SDL.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 vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx, const Emulator::VulkanQueues& queues);
|
||||
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
|
Loading…
Reference in New Issue