mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2024-12-29 11:06:07 +00:00
more on buffer rendering, added vulkan command pool
This commit is contained in:
parent
3b853413c7
commit
abe6d39295
|
@ -6,6 +6,16 @@
|
|||
|
||||
namespace HLE::Libs::Graphics {
|
||||
|
||||
struct VulkanCommandPool {
|
||||
Lib::Mutex mutex;
|
||||
VkCommandPool pool = nullptr;
|
||||
VkCommandBuffer* buffers = nullptr;
|
||||
VkFence* fences = nullptr;
|
||||
VkSemaphore* semaphores = nullptr;
|
||||
bool* busy = nullptr;
|
||||
u32 buffers_count = 0;
|
||||
};
|
||||
|
||||
struct VulkanQueueInfo {
|
||||
Lib::Mutex* mutex = nullptr;
|
||||
u32 family = static_cast<u32>(-1);
|
||||
|
|
|
@ -1,9 +1,198 @@
|
|||
#include "graphics_render.h"
|
||||
|
||||
#include "Util/Singleton.h"
|
||||
#include "emulator.h"
|
||||
|
||||
static thread_local GPU::CommandPool g_command_pool;
|
||||
|
||||
void GPU::renderCreateCtx() {
|
||||
auto* render_ctx = Singleton<RenderCtx>::Instance();
|
||||
|
||||
render_ctx->setGraphicCtx(Emulator::getGraphicCtx());
|
||||
}
|
||||
|
||||
void GPU::CommandBuffer::allocateBuffer() {
|
||||
m_pool = g_command_pool.getPool(m_queue);
|
||||
|
||||
Lib::LockMutexGuard lock(m_pool->mutex);
|
||||
|
||||
for (uint32_t i = 0; i < m_pool->buffers_count; i++) {
|
||||
if (!m_pool->busy[i]) {
|
||||
m_pool->busy[i] = true;
|
||||
vkResetCommandBuffer(m_pool->buffers[i], VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
|
||||
m_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPU::CommandBuffer::freeBuffer() {
|
||||
Lib::LockMutexGuard lock(m_pool->mutex);
|
||||
|
||||
waitForFence();
|
||||
|
||||
m_pool->busy[m_index] = false;
|
||||
vkResetCommandBuffer(m_pool->buffers[m_index], VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
|
||||
m_index = static_cast<uint32_t>(-1);
|
||||
}
|
||||
|
||||
void GPU::CommandBuffer::waitForFence() {
|
||||
auto* render_ctx = Singleton<RenderCtx>::Instance();
|
||||
|
||||
if (m_execute) {
|
||||
auto* device = render_ctx->getGraphicCtx()->m_device;
|
||||
|
||||
vkWaitForFences(device, 1, &m_pool->fences[m_index], VK_TRUE, UINT64_MAX);
|
||||
vkResetFences(device, 1, &m_pool->fences[m_index]);
|
||||
|
||||
m_execute = false;
|
||||
}
|
||||
}
|
||||
void GPU::CommandBuffer::begin() const {
|
||||
auto* buffer = m_pool->buffers[m_index];
|
||||
|
||||
VkCommandBufferBeginInfo begin_info{};
|
||||
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
begin_info.pNext = nullptr;
|
||||
begin_info.flags = 0;
|
||||
begin_info.pInheritanceInfo = nullptr;
|
||||
|
||||
auto result = vkBeginCommandBuffer(buffer, &begin_info);
|
||||
|
||||
if (result != VK_SUCCESS) {
|
||||
printf("vkBeginCommandBuffer failed\n");
|
||||
std::exit(0);
|
||||
}
|
||||
}
|
||||
void GPU::CommandBuffer::end() const {
|
||||
auto* buffer = m_pool->buffers[m_index];
|
||||
|
||||
auto result = vkEndCommandBuffer(buffer);
|
||||
|
||||
if (result != VK_SUCCESS) {
|
||||
printf("vkEndCommandBuffer failed\n");
|
||||
std::exit(0);
|
||||
}
|
||||
}
|
||||
void GPU::CommandBuffer::executeWithSemaphore() {
|
||||
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 = 1;
|
||||
submit_info.pSignalSemaphores = &m_pool->semaphores[m_index];
|
||||
|
||||
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->LockMutex();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
m_pool[id] = new HLE::Libs::Graphics::VulkanCommandPool;
|
||||
|
||||
VkCommandPoolCreateInfo pool_info{};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
pool_info.pNext = nullptr;
|
||||
pool_info.queueFamilyIndex = ctx->queues[id].family;
|
||||
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
|
||||
vkCreateCommandPool(ctx->m_device, &pool_info, nullptr, &m_pool[id]->pool);
|
||||
|
||||
if (m_pool[id]->pool == nullptr) {
|
||||
printf("pool is nullptr");
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
m_pool[id]->buffers_count = 4;
|
||||
m_pool[id]->buffers = new VkCommandBuffer[m_pool[id]->buffers_count];
|
||||
m_pool[id]->fences = new VkFence[m_pool[id]->buffers_count];
|
||||
m_pool[id]->semaphores = new VkSemaphore[m_pool[id]->buffers_count];
|
||||
m_pool[id]->busy = new bool[m_pool[id]->buffers_count];
|
||||
|
||||
VkCommandBufferAllocateInfo alloc_info{};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
alloc_info.commandPool = m_pool[id]->pool;
|
||||
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
alloc_info.commandBufferCount = m_pool[id]->buffers_count;
|
||||
|
||||
if (vkAllocateCommandBuffers(ctx->m_device, &alloc_info, m_pool[id]->buffers) != VK_SUCCESS) {
|
||||
printf("Can't allocate command buffers\n");
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < m_pool[id]->buffers_count; i++) {
|
||||
m_pool[id]->busy[i] = false;
|
||||
|
||||
VkFenceCreateInfo fence_info{};
|
||||
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
fence_info.pNext = nullptr;
|
||||
fence_info.flags = 0;
|
||||
|
||||
if (vkCreateFence(ctx->m_device, &fence_info, nullptr, &m_pool[id]->fences[i]) != VK_SUCCESS) {
|
||||
printf("Can't create fence\n");
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
VkSemaphoreCreateInfo semaphore_info{};
|
||||
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
semaphore_info.pNext = nullptr;
|
||||
semaphore_info.flags = 0;
|
||||
|
||||
if (vkCreateSemaphore(ctx->m_device, &semaphore_info, nullptr, &m_pool[id]->semaphores[i]) != VK_SUCCESS) {
|
||||
printf("Can't create semas\n");
|
||||
std::exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPU::CommandPool::deleteAllPool() {
|
||||
auto* render_ctx = Singleton<RenderCtx>::Instance();
|
||||
auto* ctx = render_ctx->getGraphicCtx();
|
||||
|
||||
for (auto& pool : m_pool) {
|
||||
if (pool != nullptr) {
|
||||
for (uint32_t i = 0; i < pool->buffers_count; i++) {
|
||||
vkDestroySemaphore(ctx->m_device, pool->semaphores[i], nullptr);
|
||||
vkDestroyFence(ctx->m_device, pool->fences[i], nullptr);
|
||||
}
|
||||
|
||||
vkFreeCommandBuffers(ctx->m_device, pool->pool, pool->buffers_count, pool->buffers);
|
||||
|
||||
vkDestroyCommandPool(ctx->m_device, pool->pool, nullptr);
|
||||
|
||||
delete[] pool->semaphores;
|
||||
delete[] pool->fences;
|
||||
delete[] pool->buffers;
|
||||
delete[] pool->busy;
|
||||
|
||||
delete pool;
|
||||
pool = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,43 @@
|
|||
|
||||
namespace GPU {
|
||||
|
||||
class CommandPool {
|
||||
public:
|
||||
CommandPool() = default;
|
||||
~CommandPool() {}
|
||||
|
||||
HLE::Libs::Graphics::VulkanCommandPool* getPool(int id) {
|
||||
if (m_pool[id] == nullptr) {
|
||||
createPool(id);
|
||||
}
|
||||
return m_pool[id];
|
||||
}
|
||||
|
||||
private:
|
||||
void createPool(int id);
|
||||
void deleteAllPool();
|
||||
|
||||
HLE::Libs::Graphics::VulkanCommandPool* m_pool[11] = {};
|
||||
};
|
||||
class CommandBuffer {
|
||||
public:
|
||||
explicit CommandBuffer(int queue) : m_queue(queue) { allocateBuffer(); }
|
||||
virtual ~CommandBuffer() { freeBuffer(); }
|
||||
void allocateBuffer();
|
||||
void freeBuffer();
|
||||
void waitForFence();
|
||||
void begin() const;
|
||||
void end() const;
|
||||
void executeWithSemaphore();
|
||||
u32 getIndex() const { return m_index; }
|
||||
HLE::Libs::Graphics::VulkanCommandPool* getPool() { return m_pool; }
|
||||
private:
|
||||
int m_queue = -1;
|
||||
u32 m_index = static_cast<u32>(-1);
|
||||
HLE::Libs::Graphics::VulkanCommandPool* m_pool = nullptr;
|
||||
bool m_execute = false;
|
||||
};
|
||||
|
||||
class Framebuffer {
|
||||
public:
|
||||
Framebuffer() {}
|
||||
|
@ -14,11 +51,12 @@ class RenderCtx {
|
|||
|
||||
virtual ~RenderCtx() {}
|
||||
void setGraphicCtx(HLE::Libs::Graphics::GraphicCtx* ctx) { m_graphic_ctx = ctx; }
|
||||
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { return m_graphic_ctx; }
|
||||
|
||||
private:
|
||||
Framebuffer* m_framebuffer = nullptr;
|
||||
HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr;
|
||||
};
|
||||
|
||||
|
||||
void renderCreateCtx();
|
||||
}; // namespace GPU
|
|
@ -1,5 +1,6 @@
|
|||
#include "emulator.h"
|
||||
|
||||
#include <Core/PS4/HLE/Graphics/graphics_render.h>
|
||||
#include <Util/Singleton.h>
|
||||
#include <vulkan_util.h>
|
||||
|
||||
|
@ -100,6 +101,100 @@ HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() {
|
|||
return &window_ctx->m_graphic_ctx;
|
||||
}
|
||||
|
||||
void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image) {}
|
||||
void DrawBuffer(HLE::Libs::Graphics::VideoOutVulkanImage* image) {
|
||||
auto* window_ctx = Singleton<Emulator::WindowCtx>::Instance();
|
||||
if (window_ctx->is_window_hidden) {
|
||||
SDL_ShowWindow(window_ctx->m_window);
|
||||
window_ctx->is_window_hidden = false;
|
||||
}
|
||||
|
||||
window_ctx->swapchain->current_index = static_cast<u32>(-1);
|
||||
|
||||
auto result = vkAcquireNextImageKHR(window_ctx->m_graphic_ctx.m_device, window_ctx->swapchain->swapchain, UINT64_MAX, nullptr,
|
||||
window_ctx->swapchain->present_complete_fence, &window_ctx->swapchain->current_index);
|
||||
|
||||
if (result != VK_SUCCESS) {
|
||||
printf("Can't aquireNextImage\n");
|
||||
std::exit(0);
|
||||
}
|
||||
if (window_ctx->swapchain->current_index == static_cast<u32>(-1)) {
|
||||
printf("Unsupported:swapchain current index is -1\n");
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
do {
|
||||
result = vkWaitForFences(window_ctx->m_graphic_ctx.m_device, 1, &window_ctx->swapchain->present_complete_fence, VK_TRUE, 100000000);
|
||||
} while (result == VK_TIMEOUT);
|
||||
if (result != VK_SUCCESS) {
|
||||
printf("vkWaitForFences is not success\n");
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
vkResetFences(window_ctx->m_graphic_ctx.m_device, 1, &window_ctx->swapchain->present_complete_fence);
|
||||
|
||||
auto* blt_src_image = image;
|
||||
auto* blt_dst_image = window_ctx->swapchain;
|
||||
|
||||
if (blt_src_image == nullptr) {
|
||||
printf("blt_src_image is null\n");
|
||||
std::exit(0);
|
||||
}
|
||||
if (blt_dst_image == nullptr) {
|
||||
printf("blt_dst_image is null\n");
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
GPU::CommandBuffer buffer(10);
|
||||
|
||||
auto* vk_buffer = buffer.getPool()->buffers[buffer.getIndex()];
|
||||
|
||||
buffer.begin();
|
||||
|
||||
//UtilBlitImage(&buffer, blt_src_image, blt_dst_image);
|
||||
|
||||
VkImageMemoryBarrier pre_present_barrier{};
|
||||
pre_present_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
pre_present_barrier.pNext = nullptr;
|
||||
pre_present_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
pre_present_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||
pre_present_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
pre_present_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
pre_present_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
pre_present_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
pre_present_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
pre_present_barrier.subresourceRange.baseMipLevel = 0;
|
||||
pre_present_barrier.subresourceRange.levelCount = 1;
|
||||
pre_present_barrier.subresourceRange.baseArrayLayer = 0;
|
||||
pre_present_barrier.subresourceRange.layerCount = 1;
|
||||
pre_present_barrier.image = window_ctx->swapchain->swapchain_images[window_ctx->swapchain->current_index];
|
||||
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1,
|
||||
&pre_present_barrier);
|
||||
|
||||
buffer.end();
|
||||
buffer.executeWithSemaphore();
|
||||
|
||||
VkPresentInfoKHR present{};
|
||||
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
present.pNext = nullptr;
|
||||
present.swapchainCount = 1;
|
||||
present.pSwapchains = &window_ctx->swapchain->swapchain;
|
||||
present.pImageIndices = &window_ctx->swapchain->current_index;
|
||||
present.pWaitSemaphores = &buffer.getPool()->semaphores[buffer.getIndex()];
|
||||
present.waitSemaphoreCount = 1;
|
||||
present.pResults = nullptr;
|
||||
|
||||
const auto& queue = window_ctx->m_graphic_ctx.queues[10];
|
||||
|
||||
if (queue.mutex != nullptr) {
|
||||
printf("queue.mutexe is null\n");
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
result = vkQueuePresentKHR(queue.vk_queue, &present);
|
||||
if (result != VK_SUCCESS) {
|
||||
printf("vkQueuePresentKHR failed\n");
|
||||
std::exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Emulator
|
Loading…
Reference in a new issue