diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp index 4e92e1fa..c96183ff 100644 --- a/src/Core/PS4/GPU/gpu_memory.cpp +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -25,6 +25,39 @@ void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) { u64 GPU::calculate_hash(const u08* buf, u64 size) { return (size > 0 && buf != nullptr ? XXH3_64bits(buf, size) : 0); } +bool GPU::vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanMemory* mem) { + static std::atomic_uint64_t unique_id = 0; + + VkPhysicalDeviceMemoryProperties memory_properties{}; + vkGetPhysicalDeviceMemoryProperties(ctx->m_physical_device, &memory_properties); + + u32 index = 0; + for (; index < memory_properties.memoryTypeCount; index++) { + if ((mem->requirements.memoryTypeBits & (static_cast(1) << index)) != 0 && + (memory_properties.memoryTypes[index].propertyFlags & mem->property) == mem->property) { + break; + } + } + + mem->type = index; + mem->offset = 0; + + VkMemoryAllocateInfo alloc_info{}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.pNext = nullptr; + alloc_info.allocationSize = mem->requirements.size; + alloc_info.memoryTypeIndex = index; + + mem->unique_id = ++unique_id; + + auto result = vkAllocateMemory(ctx->m_device, &alloc_info, nullptr, &mem->memory); + + if (result == VK_SUCCESS) { + return true; + } + return false; +} + int GPU::GPUMemory::getHeapId(u64 virtual_addr, u64 size) { int index = 0; for (const auto& heap : m_heaps) { diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h index 05ef74e7..eb234b44 100644 --- a/src/Core/PS4/GPU/gpu_memory.h +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -50,14 +50,18 @@ class GPUObject { bool isReadOnly = false; MemoryObjectType objectType = MemoryObjectType::InvalidObj; - using create_func_t = void* (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* vaddr, const u64* size, int vaddr_num, + using create_func_t = void* (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* virtual_addr, const u64* size, int virtual_addr_num, HLE::Libs::Graphics::VulkanMemory* mem); + using update_func_t = void (*)(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, void* obj, const u64* virtual_addr, const u64* size, + int virtual_addr_num); virtual create_func_t getCreateFunc() const = 0; + virtual update_func_t getUpdateFunc() const = 0; }; void memorySetAllocArea(u64 virtual_addr, u64 size); void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, u64 virtual_addr, u64 size, const GPUObject& info); u64 calculate_hash(const u08* buf, u64 size); +bool vulkanAllocateMemory(HLE::Libs::Graphics::GraphicCtx* ctx, HLE::Libs::Graphics::VulkanMemory* mem); } // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/GPU/video_out_buffer.cpp b/src/Core/PS4/GPU/video_out_buffer.cpp index 1f4c8fe3..00455b5c 100644 --- a/src/Core/PS4/GPU/video_out_buffer.cpp +++ b/src/Core/PS4/GPU/video_out_buffer.cpp @@ -1,8 +1,115 @@ #include "video_out_buffer.h" -static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, const u64* vaddr, const u64* size, int vaddr_num, +#include + +#include "debug.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) {} + +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) { - return nullptr;//TODO + auto pixel_format = params[GPU::VideoOutBufferObj::PIXEL_FORMAT_PARAM]; + auto width = params[GPU::VideoOutBufferObj::WIDTH_PARAM]; + auto height = params[GPU::VideoOutBufferObj::HEIGHT_PARAM]; + + auto* vk_obj = new HLE::Libs::Graphics::VideoOutVulkanImage; + + VkFormat vk_format = VK_FORMAT_UNDEFINED; + + switch (pixel_format) { + case static_cast(GPU::VideoOutBufferFormat::R8G8B8A8Srgb): vk_format = VK_FORMAT_R8G8B8A8_SRGB; break; + case static_cast(GPU::VideoOutBufferFormat::B8G8R8A8Srgb): vk_format = VK_FORMAT_B8G8R8A8_SRGB; break; + default: LOG_CRITICAL_IF(log_file_videoOutBuffer, "unknown pixelFormat = {}\n", pixel_format); std::exit(0); + } + + vk_obj->extent.width = width; + vk_obj->extent.height = height; + vk_obj->format = vk_format; + vk_obj->image = nullptr; + vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED; + + for (auto& view : vk_obj->image_view) { + view = nullptr; + } + + VkImageCreateInfo image_info{}; + image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_info.pNext = nullptr; + image_info.flags = 0; + image_info.imageType = VK_IMAGE_TYPE_2D; + image_info.extent.width = vk_obj->extent.width; + image_info.extent.height = vk_obj->extent.height; + image_info.extent.depth = 1; + image_info.mipLevels = 1; + image_info.arrayLayers = 1; + image_info.format = vk_obj->format; + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_info.initialLayout = vk_obj->layout; + image_info.usage = + static_cast(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT) | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + + vkCreateImage(ctx->m_device, &image_info, nullptr, &vk_obj->image); + + if (vk_obj->image == nullptr) { + LOG_CRITICAL_IF(log_file_videoOutBuffer, "vk_obj->image is null\n"); + std::exit(0); + } + + vkGetImageMemoryRequirements(ctx->m_device, vk_obj->image, &mem->requirements); + + mem->property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + + bool allocated = GPU::vulkanAllocateMemory(ctx, mem); + + if (!allocated) { + LOG_CRITICAL_IF(log_file_videoOutBuffer, "can't allocate vulkan memory\n"); + std::exit(0); + } + + vkBindImageMemory(ctx->m_device, vk_obj->image, mem->memory, mem->offset); + + vk_obj->memory = *mem; + + LOG_INFO_IF(log_file_videoOutBuffer, "videoOutBuffer create object\n"); + LOG_INFO_IF(log_file_videoOutBuffer, "mem requirements.size = {}\n", mem->requirements.size); + LOG_INFO_IF(log_file_videoOutBuffer, "width = {}\n", width); + LOG_INFO_IF(log_file_videoOutBuffer, "height = {}\n", height); + LOG_INFO_IF(log_file_videoOutBuffer, "size = {}\n", *size); + + update_func(ctx, params, vk_obj, virtual_addr, size, virtual_addr_num); + + VkImageViewCreateInfo create_info{}; + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.image = vk_obj->image; + create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + create_info.format = vk_obj->format; + create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + create_info.subresourceRange.baseArrayLayer = 0; + create_info.subresourceRange.baseMipLevel = 0; + create_info.subresourceRange.layerCount = 1; + create_info.subresourceRange.levelCount = 1; + + vkCreateImageView(ctx->m_device, &create_info, nullptr, &vk_obj->image_view[HLE::Libs::Graphics::VulkanImage::VIEW_DEFAULT]); + + if (vk_obj->image_view[HLE::Libs::Graphics::VulkanImage::VIEW_DEFAULT] == nullptr) { + LOG_CRITICAL_IF(log_file_videoOutBuffer, "vk_obj->image_view is null\n"); + std::exit(0); + } + + return vk_obj; } -GPU::GPUObject::create_func_t GPU::VideoOutBufferObj::getCreateFunc() const { return create_func; } \ No newline at end of file +GPU::GPUObject::create_func_t GPU::VideoOutBufferObj::getCreateFunc() const { return create_func; } + +GPU::GPUObject::update_func_t GPU::VideoOutBufferObj::getUpdateFunc() const { return update_func; } diff --git a/src/Core/PS4/GPU/video_out_buffer.h b/src/Core/PS4/GPU/video_out_buffer.h index 65da864b..ed459efe 100644 --- a/src/Core/PS4/GPU/video_out_buffer.h +++ b/src/Core/PS4/GPU/video_out_buffer.h @@ -33,5 +33,6 @@ class VideoOutBufferObj : public GPUObject { } create_func_t getCreateFunc() const override; + update_func_t getUpdateFunc() const override; }; } // namespace GPU