mirror of
https://github.com/InoriRus/Kyty.git
synced 2026-08-27 20:56:41 +00:00
render to texture
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
version: 0.0.8.build-{build}
|
||||
version: 0.0.9.build-{build}
|
||||
image: Visual Studio 2019
|
||||
environment:
|
||||
matrix:
|
||||
|
||||
@@ -82,7 +82,7 @@ if (KYTY_LINKER STREQUAL LD)
|
||||
set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000")
|
||||
endif()
|
||||
|
||||
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.8)
|
||||
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.9)
|
||||
|
||||
include(src_script.cmake)
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ file(GLOB emulator_src
|
||||
src/*.cpp
|
||||
src/Libs/*.cpp
|
||||
src/Graphics/*.cpp
|
||||
src/Graphics/Objects/*.cpp
|
||||
src/Kernel/*.cpp
|
||||
include/*.h
|
||||
)
|
||||
|
||||
@@ -65,31 +65,30 @@ struct VulkanMemory
|
||||
uint64_t unique_id = 0;
|
||||
};
|
||||
|
||||
struct VideoOutVulkanImage
|
||||
struct VulkanImage
|
||||
{
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkExtent2D extent = {};
|
||||
VkImage image = nullptr;
|
||||
VkImageView image_view = nullptr;
|
||||
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
Graphics::VulkanMemory memory;
|
||||
};
|
||||
|
||||
struct DepthStencilVulkanImage
|
||||
struct VideoOutVulkanImage: public VulkanImage
|
||||
{
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkExtent2D extent = {};
|
||||
VkImage image = nullptr;
|
||||
VkImageView image_view = nullptr;
|
||||
Graphics::VulkanMemory memory;
|
||||
};
|
||||
|
||||
struct TextureVulkanImage
|
||||
struct DepthStencilVulkanImage: public VulkanImage
|
||||
{
|
||||
};
|
||||
|
||||
struct TextureVulkanImage: public VulkanImage
|
||||
{
|
||||
};
|
||||
|
||||
struct RenderTextureVulkanImage: public VulkanImage
|
||||
{
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkExtent2D extent = {};
|
||||
VkImage image = nullptr;
|
||||
VkImageView image_view = nullptr;
|
||||
Graphics::VulkanMemory memory;
|
||||
};
|
||||
|
||||
struct VulkanBuffer
|
||||
|
||||
@@ -16,6 +16,7 @@ class CommandProcessor;
|
||||
struct VideoOutVulkanImage;
|
||||
struct DepthStencilVulkanImage;
|
||||
struct TextureVulkanImage;
|
||||
struct RenderTextureVulkanImage;
|
||||
struct VulkanCommandPool;
|
||||
struct VulkanBuffer;
|
||||
struct VulkanFramebuffer;
|
||||
@@ -82,11 +83,14 @@ void GraphicsRenderWriteBack();
|
||||
void GraphicsRenderDispatchDirect(CommandBuffer* buffer, HardwareContext* ctx, uint32_t thread_group_x, uint32_t thread_group_y,
|
||||
uint32_t thread_group_z, uint32_t mode);
|
||||
void GraphicsRenderMemoryBarrier(CommandBuffer* buffer);
|
||||
void GraphicsRenderRenderTextureBarrier(CommandBuffer* buffer, uint64_t vaddr, uint64_t size);
|
||||
|
||||
void DeleteFramebuffer(VideoOutVulkanImage* image);
|
||||
void DeleteFramebuffer(DepthStencilVulkanImage* image);
|
||||
void DeleteFramebuffer(RenderTextureVulkanImage* image);
|
||||
void DeleteDescriptor(VulkanBuffer* buffer);
|
||||
void DeleteDescriptor(TextureVulkanImage* image);
|
||||
void DeleteDescriptor(RenderTextureVulkanImage* image);
|
||||
|
||||
int GraphicsRenderAddEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id, void* udata);
|
||||
int GraphicsRenderDeleteEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id);
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_DEPTHSTENCILBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_DEPTHSTENCILBUFFER_H_
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_DEPTHSTENCILBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_DEPTHSTENCILBUFFER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
@@ -45,4 +45,4 @@ public:
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_DEPTHSTENCILBUFFER_H_ */
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_DEPTHSTENCILBUFFER_H_ */
|
||||
+22
-14
@@ -1,7 +1,8 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GPUMEMORY_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GPUMEMORY_H_
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_GPUMEMORY_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_GPUMEMORY_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/Vector.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
@@ -12,9 +13,7 @@ namespace Kyty::Libs::Graphics {
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
struct VulkanBuffer;
|
||||
struct TextureVulkanImage;
|
||||
struct VideoOutVulkanImage;
|
||||
struct DepthStencilVulkanImage;
|
||||
struct VulkanImage;
|
||||
|
||||
enum class GpuMemoryMode
|
||||
{
|
||||
@@ -24,7 +23,7 @@ enum class GpuMemoryMode
|
||||
ReadWrite
|
||||
};
|
||||
|
||||
enum class GpuMemoryObjectType
|
||||
enum class GpuMemoryObjectType : uint64_t
|
||||
{
|
||||
Invalid,
|
||||
VideoOutBuffer,
|
||||
@@ -33,7 +32,16 @@ enum class GpuMemoryObjectType
|
||||
IndexBuffer,
|
||||
VertexBuffer,
|
||||
StorageBuffer,
|
||||
Texture
|
||||
Texture,
|
||||
RenderTexture,
|
||||
|
||||
Max
|
||||
};
|
||||
|
||||
struct GpuMemoryObject
|
||||
{
|
||||
GpuMemoryObjectType type = GpuMemoryObjectType::Invalid;
|
||||
void* obj = nullptr;
|
||||
};
|
||||
|
||||
class GpuObject
|
||||
@@ -68,21 +76,21 @@ void GpuMemoryInit();
|
||||
|
||||
void GpuMemorySetAllocatedRange(uint64_t vaddr, uint64_t size);
|
||||
void GpuMemoryFree(GraphicContext* ctx, uint64_t vaddr, uint64_t size);
|
||||
void* GpuMemoryGetObject(GraphicContext* ctx, uint64_t vaddr, uint64_t size, const GpuObject& info);
|
||||
void* GpuMemoryGetObject(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, const GpuObject& info);
|
||||
void GpuMemoryResetHash(GraphicContext* ctx, uint64_t vaddr, uint64_t size, GpuMemoryObjectType type);
|
||||
void* GpuMemoryCreateObject(GraphicContext* ctx, uint64_t vaddr, uint64_t size, const GpuObject& info);
|
||||
void* GpuMemoryCreateObject(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, const GpuObject& info);
|
||||
void GpuMemoryResetHash(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, GpuMemoryObjectType type);
|
||||
void GpuMemoryDbgDump();
|
||||
void GpuMemoryFlush(GraphicContext* ctx);
|
||||
void GpuMemoryFrameDone();
|
||||
void GpuMemoryWriteBack(GraphicContext* ctx);
|
||||
|
||||
Vector<GpuMemoryObject> GpuMemoryFindObjects(uint64_t vaddr, uint64_t size);
|
||||
|
||||
bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* mem);
|
||||
void VulkanFree(GraphicContext* ctx, VulkanMemory* mem);
|
||||
void VulkanMapMemory(GraphicContext* ctx, VulkanMemory* mem, void** data);
|
||||
void VulkanUnmapMemory(GraphicContext* ctx, VulkanMemory* mem);
|
||||
void VulkanBindImageMemory(GraphicContext* ctx, TextureVulkanImage* image, VulkanMemory* mem);
|
||||
void VulkanBindImageMemory(GraphicContext* ctx, VideoOutVulkanImage* image, VulkanMemory* mem);
|
||||
void VulkanBindImageMemory(GraphicContext* ctx, DepthStencilVulkanImage* image, VulkanMemory* mem);
|
||||
void VulkanBindImageMemory(GraphicContext* ctx, VulkanImage* image, VulkanMemory* mem);
|
||||
void VulkanBindBufferMemory(GraphicContext* ctx, VulkanBuffer* buffer, VulkanMemory* mem);
|
||||
|
||||
void GpuMemoryRegisterOwner(uint32_t* owner_handle, const char* name);
|
||||
@@ -96,4 +104,4 @@ void GpuMemoryUnregisterResource(uint32_t resource_handle);
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_GPUMEMORY_H_ */
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_GPUMEMORY_H_ */
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_INDEXBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_INDEXBUFFER_H_
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_INDEXBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_INDEXBUFFER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
@@ -34,4 +34,4 @@ public:
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_INDEXBUFFER_H_ */
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_INDEXBUFFER_H_ */
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_LABEL_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_LABEL_H_
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_LABEL_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_LABEL_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
@@ -60,4 +60,4 @@ void LabelSet(CommandBuffer* buffer, Label* label);
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_LABEL_H_ */
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_LABEL_H_ */
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_RENDERTEXTURE_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_RENDERTEXTURE_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
enum class RenderTextureFormat : uint64_t
|
||||
{
|
||||
R8G8B8A8Unorm
|
||||
};
|
||||
|
||||
class RenderTextureObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
static constexpr int PARAM_FORMAT = 0;
|
||||
static constexpr int PARAM_WIDTH = 1;
|
||||
static constexpr int PARAM_HEIGHT = 2;
|
||||
static constexpr int PARAM_TILED = 3;
|
||||
static constexpr int PARAM_NEO = 4;
|
||||
static constexpr int PARAM_PITCH = 5;
|
||||
|
||||
explicit RenderTextureObject(RenderTextureFormat pixel_format, uint32_t width, uint32_t height, bool tiled, bool neo, uint32_t pitch)
|
||||
{
|
||||
params[PARAM_FORMAT] = static_cast<uint64_t>(pixel_format);
|
||||
params[PARAM_WIDTH] = width;
|
||||
params[PARAM_HEIGHT] = height;
|
||||
params[PARAM_TILED] = tiled ? 1 : 0;
|
||||
params[PARAM_NEO] = neo ? 1 : 0;
|
||||
params[PARAM_PITCH] = pitch;
|
||||
check_hash = true;
|
||||
type = Graphics::GpuMemoryObjectType::RenderTexture;
|
||||
}
|
||||
|
||||
void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const override;
|
||||
bool Equal(const uint64_t* other) const override;
|
||||
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_RENDERTEXTURE_H_ */
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_STORAGEBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_STORAGEBUFFER_H_
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_STORAGEBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_STORAGEBUFFER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
@@ -37,4 +37,4 @@ public:
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_STORAGEBUFFER_H_ */
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_STORAGEBUFFER_H_ */
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TEXTURE_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TEXTURE_H_
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_TEXTURE_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_TEXTURE_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
static constexpr int PARAM_NEO = 6;
|
||||
static constexpr int PARAM_SWIZZLE = 7;
|
||||
|
||||
TextureObject(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t pitch, uint32_t levels, bool htile, bool neo,
|
||||
TextureObject(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t pitch, uint32_t levels, uint32_t tile, bool neo,
|
||||
uint32_t swizzle, uint32_t usage)
|
||||
{
|
||||
params[PARAM_DFMT_NFMT] = (static_cast<uint64_t>(dfmt) << 32u) | nfmt;
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
params[PARAM_WIDTH_HEIGHT] = (static_cast<uint64_t>(width) << 32u) | height;
|
||||
params[PARAM_USAGE] = usage;
|
||||
params[PARAM_LEVELS] = levels;
|
||||
params[PARAM_TILE] = htile ? 1 : 0;
|
||||
params[PARAM_TILE] = tile;
|
||||
params[PARAM_NEO] = neo ? 1 : 0;
|
||||
params[PARAM_SWIZZLE] = swizzle;
|
||||
check_hash = true;
|
||||
@@ -55,4 +55,4 @@ public:
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_TEXTURE_H_ */
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_TEXTURE_H_ */
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VERTEXBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VERTEXBUFFER_H_
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_VERTEXBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_VERTEXBUFFER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
@@ -34,4 +34,4 @@ public:
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VERTEXBUFFER_H_ */
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_VERTEXBUFFER_H_ */
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUTBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUTBUFFER_H_
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_VIDEOOUTBUFFER_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_VIDEOOUTBUFFER_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
@@ -47,4 +47,4 @@ public:
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_VIDEOOUTBUFFER_H_ */
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_VIDEOOUTBUFFER_H_ */
|
||||
@@ -15,6 +15,8 @@ enum class TileMode
|
||||
VideoOutTiled,
|
||||
TextureLinear,
|
||||
TextureTiled,
|
||||
// RenderTextureLinear,
|
||||
// RenderTextureTiled,
|
||||
};
|
||||
|
||||
void TileInit();
|
||||
@@ -25,8 +27,8 @@ void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_
|
||||
void TileGetDepthSize(uint32_t width, uint32_t height, uint32_t z_format, uint32_t stencil_format, bool htile, bool neo,
|
||||
uint32_t* stencil_size, uint32_t* htile_size, uint32_t* depth_size, uint32_t* pitch);
|
||||
void TileGetVideoOutSize(uint32_t width, uint32_t height, bool tile, bool neo, uint32_t* size, uint32_t* pitch);
|
||||
void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t pitch, uint32_t levels, bool tile, bool neo,
|
||||
uint32_t* total_size, uint32_t* level_sizes, uint32_t* padded_width, uint32_t* padded_height);
|
||||
void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t pitch, uint32_t levels, uint32_t tile,
|
||||
bool neo, uint32_t* total_size, uint32_t* level_sizes, uint32_t* padded_width, uint32_t* padded_height);
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Kyty::Libs::Graphics {
|
||||
class CommandBuffer;
|
||||
struct GraphicContext;
|
||||
struct VulkanBuffer;
|
||||
struct VideoOutVulkanImage;
|
||||
struct VulkanImage;
|
||||
struct TextureVulkanImage;
|
||||
struct DepthStencilVulkanImage;
|
||||
struct VulkanSwapchain;
|
||||
@@ -30,16 +30,16 @@ struct BufferImageCopy
|
||||
uint32_t pitch;
|
||||
};
|
||||
|
||||
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, uint32_t src_pitch, VideoOutVulkanImage* dst_image);
|
||||
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, uint32_t src_pitch, VulkanImage* dst_image);
|
||||
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, TextureVulkanImage* dst_image,
|
||||
const Vector<BufferImageCopy>& regions, uint64_t dst_layout);
|
||||
void UtilBlitImage(CommandBuffer* buffer, VideoOutVulkanImage* src_image, VulkanSwapchain* dst_swapchain);
|
||||
void UtilFillImage(GraphicContext* ctx, VideoOutVulkanImage* dst_image, const void* src_data, uint64_t size, uint32_t src_pitch);
|
||||
void UtilBlitImage(CommandBuffer* buffer, VulkanImage* src_image, VulkanSwapchain* dst_swapchain);
|
||||
void UtilFillImage(GraphicContext* ctx, VulkanImage* dst_image, const void* src_data, uint64_t size, uint32_t src_pitch);
|
||||
void UtilFillImage(GraphicContext* ctx, TextureVulkanImage* dst_image, const void* src_data, uint64_t size,
|
||||
const Vector<BufferImageCopy>& regions, uint64_t dst_layout);
|
||||
void UtilCopyBuffer(VulkanBuffer* src_buffer, VulkanBuffer* dst_buffer, uint64_t size);
|
||||
void UtilSetImageLayoutOptimal(DepthStencilVulkanImage* image);
|
||||
void UtilSetImageLayoutOptimal(VideoOutVulkanImage* image);
|
||||
void UtilSetDepthLayoutOptimal(DepthStencilVulkanImage* image);
|
||||
void UtilSetImageLayoutOptimal(VulkanImage* image);
|
||||
|
||||
void VulkanCreateBuffer(GraphicContext* gctx, uint64_t size, VulkanBuffer* buffer);
|
||||
void VulkanDeleteBuffer(GraphicContext* gctx, VulkanBuffer* buffer);
|
||||
|
||||
@@ -1,960 +0,0 @@
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
#include "Kyty/Core/MagicEnum.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
#include "Kyty/Core/Threads.h"
|
||||
#include "Kyty/Core/Vector.h"
|
||||
|
||||
#include "Emulator/Graphics/GraphicContext.h"
|
||||
#include "Emulator/Profiler.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
//#define XXH_INLINE_ALL
|
||||
#include <xxhash/xxhash.h>
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
class GpuMemory
|
||||
{
|
||||
public:
|
||||
GpuMemory() { EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread()); }
|
||||
virtual ~GpuMemory() { KYTY_NOT_IMPLEMENTED; }
|
||||
KYTY_CLASS_NO_COPY(GpuMemory);
|
||||
|
||||
bool IsAllocated(uint64_t vaddr, uint64_t size);
|
||||
void SetAllocatedRange(uint64_t vaddr, uint64_t size);
|
||||
void Free(GraphicContext* ctx, uint64_t vaddr, uint64_t size);
|
||||
|
||||
void* GetObject(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, const GpuObject& info);
|
||||
void ResetHash(GraphicContext* ctx, uint64_t* vaddr, uint64_t* size, int vaddr_num, GpuMemoryObjectType type);
|
||||
void FrameDone();
|
||||
|
||||
// Sync: GPU -> CPU
|
||||
void WriteBack(GraphicContext* ctx);
|
||||
|
||||
// Sync: CPU -> GPU
|
||||
void Flush(GraphicContext* ctx);
|
||||
|
||||
void DbgDump();
|
||||
|
||||
private:
|
||||
static constexpr int OBJ_OVERLAPS_MAX = 2;
|
||||
static constexpr int VADDR_BLOCKS_MAX = 3;
|
||||
|
||||
struct AllocatedRange
|
||||
{
|
||||
uint64_t vaddr;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
struct ObjectInfo
|
||||
{
|
||||
void* obj = nullptr;
|
||||
uint64_t params[GpuObject::PARAMS_MAX] = {};
|
||||
GpuMemoryObjectType type = GpuMemoryObjectType::Invalid;
|
||||
uint64_t hash[VADDR_BLOCKS_MAX] = {};
|
||||
GpuObject::write_back_func_t write_back_func = nullptr;
|
||||
GpuObject::delete_func_t delete_func = nullptr;
|
||||
GpuObject::update_func_t update_func = nullptr;
|
||||
uint64_t use_last_frame = 0;
|
||||
uint64_t use_num = 0;
|
||||
bool in_use = false;
|
||||
bool read_only = false;
|
||||
bool check_hash = false;
|
||||
VulkanMemory mem;
|
||||
};
|
||||
|
||||
struct Object
|
||||
{
|
||||
uint64_t vaddr[VADDR_BLOCKS_MAX] = {};
|
||||
uint64_t size[VADDR_BLOCKS_MAX] = {};
|
||||
int vaddr_num = 0;
|
||||
ObjectInfo overlaps[OBJ_OVERLAPS_MAX];
|
||||
int overlaps_num = 0;
|
||||
bool free = true;
|
||||
};
|
||||
|
||||
void Free(GraphicContext* ctx, Object& h);
|
||||
|
||||
Core::Mutex m_mutex;
|
||||
|
||||
Vector<AllocatedRange> m_allocated;
|
||||
Vector<Object> m_objects;
|
||||
uint64_t m_objects_size = 0;
|
||||
uint64_t m_current_frame = 0;
|
||||
};
|
||||
|
||||
class GpuResources
|
||||
{
|
||||
public:
|
||||
struct Info
|
||||
{
|
||||
uint32_t owner = 0;
|
||||
bool free = true;
|
||||
uint64_t memory = 0;
|
||||
size_t size = 0;
|
||||
String name;
|
||||
uint32_t type = 0;
|
||||
uint64_t user_data = 0;
|
||||
};
|
||||
|
||||
GpuResources() { EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread()); }
|
||||
virtual ~GpuResources() { KYTY_NOT_IMPLEMENTED; }
|
||||
KYTY_CLASS_NO_COPY(GpuResources);
|
||||
|
||||
uint32_t AddOwner(const String& name);
|
||||
uint32_t AddResource(uint32_t owner_handle, uint64_t memory, size_t size, const String& name, uint32_t type, uint64_t user_data);
|
||||
void DeleteOwner(uint32_t owner_handle);
|
||||
void DeleteResources(uint32_t owner_handle);
|
||||
void DeleteResource(uint32_t resource_handle);
|
||||
|
||||
bool FindInfo(uint64_t memory, Info* dst);
|
||||
|
||||
private:
|
||||
struct Owner
|
||||
{
|
||||
String name;
|
||||
bool free = true;
|
||||
};
|
||||
|
||||
Core::Mutex m_mutex;
|
||||
|
||||
Vector<Owner> m_owners;
|
||||
Vector<Info> m_infos;
|
||||
};
|
||||
|
||||
static GpuMemory* g_gpu_memory = nullptr;
|
||||
static GpuResources* g_gpu_resources = nullptr;
|
||||
|
||||
uint32_t GpuResources::AddOwner(const String& name)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
Owner n;
|
||||
n.name = name;
|
||||
n.free = false;
|
||||
|
||||
uint32_t index = 0;
|
||||
for (auto& b: m_owners)
|
||||
{
|
||||
if (b.free)
|
||||
{
|
||||
b = n;
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
m_owners.Add(n);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
uint32_t GpuResources::AddResource(uint32_t owner_handle, uint64_t memory, size_t size, const String& name, uint32_t type,
|
||||
uint64_t user_data)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(!m_owners.IndexValid(owner_handle));
|
||||
EXIT_NOT_IMPLEMENTED(memory == 0);
|
||||
|
||||
Info info;
|
||||
info.owner = owner_handle;
|
||||
info.memory = memory;
|
||||
info.free = false;
|
||||
info.name = name;
|
||||
info.size = size;
|
||||
info.type = type;
|
||||
info.user_data = user_data;
|
||||
|
||||
uint32_t index = 0;
|
||||
for (auto& i: m_infos)
|
||||
{
|
||||
if (i.free)
|
||||
{
|
||||
i = info;
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
m_infos.Add(info);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void GpuResources::DeleteOwner(uint32_t owner_handle)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(!m_owners.IndexValid(owner_handle));
|
||||
|
||||
for (auto& i: m_infos)
|
||||
{
|
||||
if (!i.free && i.owner == owner_handle)
|
||||
{
|
||||
i.free = true;
|
||||
}
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(m_owners[owner_handle].free);
|
||||
|
||||
m_owners[owner_handle].free = true;
|
||||
}
|
||||
|
||||
void GpuResources::DeleteResources(uint32_t owner_handle)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(!m_owners.IndexValid(owner_handle));
|
||||
|
||||
for (auto& i: m_infos)
|
||||
{
|
||||
if (!i.free && i.owner == owner_handle)
|
||||
{
|
||||
i.free = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GpuResources::DeleteResource(uint32_t resource_handle)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(!m_infos.IndexValid(resource_handle));
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(m_infos[resource_handle].free);
|
||||
|
||||
m_infos[resource_handle].free = true;
|
||||
}
|
||||
|
||||
bool GpuResources::FindInfo(uint64_t memory, Info* dst)
|
||||
{
|
||||
EXIT_IF(dst == nullptr);
|
||||
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
// NOLINTNEXTLINE(readability-use-anyofallof)
|
||||
for (const auto& i: m_infos)
|
||||
{
|
||||
if (!i.free && memory >= i.memory && memory < i.memory + i.size)
|
||||
{
|
||||
*dst = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GpuMemory::SetAllocatedRange(uint64_t vaddr, uint64_t size)
|
||||
{
|
||||
EXIT_IF(size == 0);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(IsAllocated(vaddr, size));
|
||||
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
AllocatedRange r {};
|
||||
r.vaddr = vaddr;
|
||||
r.size = size;
|
||||
|
||||
m_allocated.Add(r);
|
||||
}
|
||||
|
||||
bool GpuMemory::IsAllocated(uint64_t vaddr, uint64_t size)
|
||||
{
|
||||
EXIT_IF(size == 0);
|
||||
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
return std::any_of(m_allocated.begin(), m_allocated.end(),
|
||||
[vaddr, size](auto& r) {
|
||||
return ((vaddr >= r.vaddr && vaddr < r.vaddr + r.size) ||
|
||||
((vaddr + size - 1) >= r.vaddr && (vaddr + size - 1) < r.vaddr + r.size));
|
||||
});
|
||||
}
|
||||
|
||||
static uint64_t calc_hash(const uint8_t* buf, uint64_t size)
|
||||
{
|
||||
KYTY_PROFILER_FUNCTION();
|
||||
|
||||
return (size > 0 && buf != nullptr ? XXH64(buf, size, 0) : 0);
|
||||
}
|
||||
|
||||
static bool vaddr_equal(const uint64_t* vaddr, const uint64_t* size, int vaddr_num, const uint64_t* vaddr2, const uint64_t* size2,
|
||||
int vaddr_num2)
|
||||
{
|
||||
if (vaddr_num != vaddr_num2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < vaddr_num; i++)
|
||||
{
|
||||
if (vaddr[i] != vaddr2[i] || size[i] != size2[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool vaddr_overlap(const uint64_t* hvaddr, const uint64_t* hsize, int vaddr_num, uint64_t vaddr, uint64_t size)
|
||||
{
|
||||
for (int i = 0; i < vaddr_num; i++)
|
||||
{
|
||||
if ((vaddr >= hvaddr[i] && vaddr < hvaddr[i] + hsize[i]) ||
|
||||
((vaddr + size - 1) >= hvaddr[i] && (vaddr + size - 1) < hvaddr[i] + hsize[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
void* GpuMemory::GetObject(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, const GpuObject& info)
|
||||
{
|
||||
EXIT_IF(info.type == GpuMemoryObjectType::Invalid);
|
||||
EXIT_IF(vaddr == nullptr || size == nullptr || vaddr_num > VADDR_BLOCKS_MAX || vaddr_num <= 0);
|
||||
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
uint64_t hash[VADDR_BLOCKS_MAX] = {};
|
||||
|
||||
for (int vi = 0; vi < vaddr_num; vi++)
|
||||
{
|
||||
EXIT_IF(size[vi] == 0);
|
||||
|
||||
if (info.check_hash)
|
||||
{
|
||||
hash[vi] = calc_hash(reinterpret_cast<const uint8_t*>(vaddr[vi]), size[vi]);
|
||||
} else
|
||||
{
|
||||
hash[vi] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Object* update_object = nullptr;
|
||||
|
||||
for (auto& h: m_objects)
|
||||
{
|
||||
if (!h.free && vaddr_equal(h.vaddr, h.size, h.vaddr_num, vaddr, size, vaddr_num))
|
||||
{
|
||||
for (int oi = 0; oi < h.overlaps_num; oi++)
|
||||
{
|
||||
auto& o = h.overlaps[oi];
|
||||
if (o.type == info.type && info.Equal(o.params))
|
||||
{
|
||||
bool need_update = false;
|
||||
for (int vi = 0; vi < h.vaddr_num; vi++)
|
||||
{
|
||||
if (o.hash[vi] != hash[vi])
|
||||
{
|
||||
printf("Update (CPU -> GPU): type = %s, vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 "\n",
|
||||
Core::EnumName(o.type).C_Str(), h.vaddr[vi], h.size[vi]);
|
||||
need_update = true;
|
||||
o.hash[vi] = hash[vi];
|
||||
}
|
||||
}
|
||||
if (need_update)
|
||||
{
|
||||
EXIT_IF(o.update_func == nullptr);
|
||||
o.update_func(ctx, o.params, o.obj, vaddr, size, vaddr_num);
|
||||
}
|
||||
o.use_num++;
|
||||
o.use_last_frame = m_current_frame;
|
||||
o.in_use = true;
|
||||
o.read_only = info.read_only;
|
||||
o.check_hash = info.check_hash;
|
||||
return o.obj;
|
||||
}
|
||||
}
|
||||
|
||||
if (h.overlaps_num == 1 &&
|
||||
(h.overlaps[0].type == GpuMemoryObjectType::VideoOutBuffer && info.type == GpuMemoryObjectType::StorageBuffer))
|
||||
{
|
||||
update_object = &h;
|
||||
break;
|
||||
}
|
||||
|
||||
// EXIT("not implemented");
|
||||
|
||||
Free(ctx, h);
|
||||
break;
|
||||
}
|
||||
|
||||
for (int vi = 0; vi < vaddr_num; vi++)
|
||||
{
|
||||
if (!h.free && vaddr_overlap(h.vaddr, h.size, h.overlaps_num, vaddr[vi], size[vi]))
|
||||
{
|
||||
if (h.overlaps_num == 1 &&
|
||||
(h.overlaps[0].type == GpuMemoryObjectType::Label || h.overlaps[0].type == GpuMemoryObjectType::StorageBuffer))
|
||||
{
|
||||
Free(ctx, h);
|
||||
} else
|
||||
{
|
||||
KYTY_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int vi = 0; vi < vaddr_num; vi++)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(!IsAllocated(vaddr[vi], size[vi]));
|
||||
}
|
||||
|
||||
ObjectInfo o {};
|
||||
|
||||
for (int i = 0; i < GpuObject::PARAMS_MAX; i++)
|
||||
{
|
||||
o.params[i] = info.params[i];
|
||||
}
|
||||
|
||||
o.type = info.type;
|
||||
o.obj = nullptr;
|
||||
for (int vi = 0; vi < vaddr_num; vi++)
|
||||
{
|
||||
o.hash[vi] = hash[vi];
|
||||
}
|
||||
o.obj = info.Create(ctx, vaddr, size, vaddr_num, &o.mem);
|
||||
o.write_back_func = info.GetWriteBackFunc();
|
||||
o.delete_func = info.GetDeleteFunc();
|
||||
o.update_func = info.GetUpdateFunc();
|
||||
o.use_num = 1;
|
||||
o.use_last_frame = m_current_frame;
|
||||
o.in_use = true;
|
||||
o.read_only = info.read_only;
|
||||
o.check_hash = info.check_hash;
|
||||
|
||||
bool updated = false;
|
||||
|
||||
if (update_object != nullptr)
|
||||
{
|
||||
EXIT_IF(update_object->overlaps_num >= OBJ_OVERLAPS_MAX);
|
||||
update_object->overlaps[update_object->overlaps_num++] = o;
|
||||
|
||||
updated = true;
|
||||
} else
|
||||
{
|
||||
for (auto& u: m_objects)
|
||||
{
|
||||
if (u.free)
|
||||
{
|
||||
u.overlaps_num = 1;
|
||||
u.overlaps[0] = o;
|
||||
u.free = false;
|
||||
for (int vi = 0; vi < vaddr_num; vi++)
|
||||
{
|
||||
u.vaddr[vi] = vaddr[vi];
|
||||
u.size[vi] = size[vi];
|
||||
m_objects_size += size[vi];
|
||||
}
|
||||
u.vaddr_num = vaddr_num;
|
||||
updated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!updated)
|
||||
{
|
||||
Object h {};
|
||||
for (int vi = 0; vi < vaddr_num; vi++)
|
||||
{
|
||||
h.vaddr[vi] = vaddr[vi];
|
||||
h.size[vi] = size[vi];
|
||||
m_objects_size += size[vi];
|
||||
}
|
||||
h.vaddr_num = vaddr_num;
|
||||
h.overlaps_num = 1;
|
||||
h.overlaps[0] = o;
|
||||
h.free = false;
|
||||
m_objects.Add(h);
|
||||
}
|
||||
|
||||
return o.obj;
|
||||
}
|
||||
|
||||
void GpuMemory::ResetHash(GraphicContext* /*ctx*/, uint64_t* vaddr, uint64_t* size, int vaddr_num, GpuMemoryObjectType type)
|
||||
{
|
||||
EXIT_IF(type == GpuMemoryObjectType::Invalid);
|
||||
EXIT_IF(vaddr == nullptr || size == nullptr || vaddr_num > VADDR_BLOCKS_MAX || vaddr_num <= 0);
|
||||
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
uint64_t new_hash = 0;
|
||||
|
||||
for (auto& h: m_objects)
|
||||
{
|
||||
if (!h.free && vaddr_equal(h.vaddr, h.size, h.vaddr_num, vaddr, size, vaddr_num))
|
||||
{
|
||||
for (int oi = 0; oi < h.overlaps_num; oi++)
|
||||
{
|
||||
auto& o = h.overlaps[oi];
|
||||
if (o.type == type)
|
||||
{
|
||||
for (int vi = 0; vi < h.vaddr_num; vi++)
|
||||
{
|
||||
printf("ResetHash: type = %s, vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 ", old_hash = 0x%016" PRIx64
|
||||
", new_hash = 0x%016" PRIx64 "\n",
|
||||
Core::EnumName(o.type).C_Str(), h.vaddr[vi], h.size[vi], o.hash[vi], new_hash);
|
||||
|
||||
o.hash[vi] = new_hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GpuMemory::Free(GraphicContext* ctx, uint64_t vaddr, uint64_t size)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
printf("Release gpu objects:\n");
|
||||
printf("\t gpu_vaddr = 0x%016" PRIx64 "\n", vaddr);
|
||||
printf("\t size = 0x%016" PRIx64 "\n", size);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(!IsAllocated(vaddr, size));
|
||||
|
||||
int index = 0;
|
||||
for (auto& a: m_allocated)
|
||||
{
|
||||
if (a.vaddr == vaddr && a.size == size)
|
||||
{
|
||||
m_allocated.RemoveAt(index);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(IsAllocated(vaddr, size));
|
||||
|
||||
for (auto& h: m_objects)
|
||||
{
|
||||
for (int vi = 0; vi < h.vaddr_num; vi++)
|
||||
{
|
||||
if (!h.free && (h.vaddr[vi] >= vaddr && h.vaddr[vi] < vaddr + size))
|
||||
{
|
||||
Free(ctx, h);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GpuMemory::Free(GraphicContext* ctx, Object& h)
|
||||
{
|
||||
for (int oi = 0; oi < h.overlaps_num; oi++)
|
||||
{
|
||||
auto& o = h.overlaps[oi];
|
||||
|
||||
EXIT_IF(o.delete_func == nullptr);
|
||||
|
||||
if (o.delete_func != nullptr)
|
||||
{
|
||||
for (int vi = 0; vi < h.vaddr_num; vi++)
|
||||
{
|
||||
printf("Delete: type = %s, vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 "\n", Core::EnumName(o.type).C_Str(),
|
||||
h.vaddr[vi], h.size[vi]);
|
||||
}
|
||||
|
||||
o.delete_func(ctx, o.obj, &o.mem);
|
||||
}
|
||||
}
|
||||
h.overlaps_num = 0;
|
||||
h.free = true;
|
||||
for (int vi = 0; vi < h.vaddr_num; vi++)
|
||||
{
|
||||
m_objects_size -= h.size[vi];
|
||||
}
|
||||
h.vaddr_num = 0;
|
||||
}
|
||||
|
||||
void GpuMemory::FrameDone()
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
m_current_frame++;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
void GpuMemory::WriteBack(GraphicContext* ctx)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
for (auto& h: m_objects)
|
||||
{
|
||||
if (!h.free)
|
||||
{
|
||||
for (int oi = 0; oi < h.overlaps_num; oi++)
|
||||
{
|
||||
auto& o = h.overlaps[oi];
|
||||
if (o.in_use && /*o.use_last_frame >= m_current_frame &&*/ o.write_back_func != nullptr && !o.read_only)
|
||||
{
|
||||
o.write_back_func(ctx, o.obj, h.vaddr, h.size, h.vaddr_num);
|
||||
|
||||
for (int vi = 0; vi < h.vaddr_num; vi++)
|
||||
{
|
||||
uint64_t new_hash = 0;
|
||||
|
||||
if (o.check_hash)
|
||||
{
|
||||
new_hash = calc_hash(reinterpret_cast<const uint8_t*>(h.vaddr[vi]), h.size[vi]);
|
||||
}
|
||||
|
||||
printf("WriteBack (GPU -> CPU): type = %s, vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64
|
||||
", old_hash = 0x%016" PRIx64 ", new_hash = 0x%016" PRIx64 "\n",
|
||||
Core::EnumName(o.type).C_Str(), h.vaddr[vi], h.size[vi], o.hash[vi], new_hash);
|
||||
|
||||
o.hash[vi] = new_hash;
|
||||
}
|
||||
|
||||
for (int oi2 = 0; oi2 < h.overlaps_num; oi2++)
|
||||
{
|
||||
if (oi2 != oi)
|
||||
{
|
||||
auto& o2 = h.overlaps[oi2];
|
||||
|
||||
bool need_update = false;
|
||||
|
||||
for (int vi = 0; vi < h.vaddr_num; vi++)
|
||||
{
|
||||
uint64_t hash = o.hash[vi];
|
||||
|
||||
if (o2.hash[vi] != hash)
|
||||
{
|
||||
printf("Update (CPU -> GPU): type = %s, vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64
|
||||
", old_hash = 0x%016" PRIx64 ", new_hash = 0x%016" PRIx64 "\n",
|
||||
Core::EnumName(o2.type).C_Str(), h.vaddr[vi], h.size[vi], o2.hash[vi], hash);
|
||||
o2.hash[vi] = hash;
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_update)
|
||||
{
|
||||
EXIT_IF(o2.update_func == nullptr);
|
||||
|
||||
o2.update_func(ctx, o2.params, o2.obj, h.vaddr, h.size, h.vaddr_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
o.in_use = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GpuMemory::Flush(GraphicContext* ctx)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
for (auto& h: m_objects)
|
||||
{
|
||||
if (!h.free)
|
||||
{
|
||||
for (int oi = 0; oi < h.overlaps_num; oi++)
|
||||
{
|
||||
auto& o = h.overlaps[oi];
|
||||
|
||||
EXIT_IF(o.update_func == nullptr);
|
||||
o.update_func(ctx, o.params, o.obj, h.vaddr, h.size, h.vaddr_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GpuMemory::DbgDump()
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
printf("--- Gpu Memory ---\n");
|
||||
|
||||
for (auto& o: m_allocated)
|
||||
{
|
||||
printf("Allocated block: vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 "\n", o.vaddr, o.size);
|
||||
}
|
||||
|
||||
printf("m_current_frame = %" PRIu64 "\n", m_current_frame);
|
||||
printf("m_objects_size = %" PRIu64 "\n", m_objects_size);
|
||||
|
||||
for (auto& h: m_objects)
|
||||
{
|
||||
if (!h.free)
|
||||
{
|
||||
printf("Object:\n");
|
||||
for (int vi = 0; vi < h.vaddr_num; vi++)
|
||||
{
|
||||
printf("\t vaddr = 0x%016" PRIx64 "\n", h.vaddr[vi]);
|
||||
printf("\t size = 0x%016" PRIx64 "\n", h.size[vi]);
|
||||
GpuResources::Info res_info;
|
||||
if (g_gpu_resources->FindInfo(h.vaddr[vi], &res_info))
|
||||
{
|
||||
printf("\t {\n");
|
||||
printf("\t\t RegisteredResource: %s\n", res_info.name.C_Str());
|
||||
printf("\t\t addr: %016" PRIx64 "\n", res_info.memory);
|
||||
printf("\t\t size: %" PRIu64 "\n", res_info.size);
|
||||
printf("\t\t type: %" PRIu32 "\n", res_info.type);
|
||||
printf("\t\t user_data: %" PRIu64 "\n", res_info.user_data);
|
||||
printf("\t }\n");
|
||||
|
||||
// EXIT_NOT_IMPLEMENTED(res_info.size != h.size[vi]);
|
||||
// EXIT_NOT_IMPLEMENTED(res_info.memory != h.vaddr[vi]);
|
||||
}
|
||||
}
|
||||
printf("\t overlaps_num = %d\n", h.overlaps_num);
|
||||
for (int oi = 0; oi < h.overlaps_num; oi++)
|
||||
{
|
||||
auto& o = h.overlaps[oi];
|
||||
printf("\t [%d] type = %s\n", oi, Core::EnumName(o.type).C_Str());
|
||||
for (int vi = 0; vi < h.vaddr_num; vi++)
|
||||
{
|
||||
printf("\t [%d] hash = 0x%016" PRIx64 "\n", oi, o.hash[vi]);
|
||||
}
|
||||
printf("\t [%d] vk_size = 0x%016" PRIx64 "\n", oi, o.mem.requirements.size);
|
||||
printf("\t [%d] vk_align = 0x%016" PRIx64 "\n", oi, o.mem.requirements.alignment);
|
||||
printf("\t [%d] vk_type = 0x%08" PRIx32 "\n", oi, o.mem.type);
|
||||
printf("\t [%d] use_last_frame = %" PRIu64 "\n", oi, o.use_last_frame);
|
||||
printf("\t [%d] use_num = %" PRIu64 "\n", oi, o.use_num);
|
||||
printf("\t [%d] in_use = %s\n", oi, o.in_use ? "true" : "false");
|
||||
printf("\t [%d] read_only = %s\n", oi, o.read_only ? "true" : "false");
|
||||
printf("\t [%d] check_hash = %s\n", oi, o.check_hash ? "true" : "false");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GpuMemoryInit()
|
||||
{
|
||||
EXIT_IF(g_gpu_memory != nullptr);
|
||||
EXIT_IF(g_gpu_resources != nullptr);
|
||||
|
||||
g_gpu_memory = new GpuMemory;
|
||||
g_gpu_resources = new GpuResources;
|
||||
}
|
||||
|
||||
void GpuMemorySetAllocatedRange(uint64_t vaddr, uint64_t size)
|
||||
{
|
||||
EXIT_IF(g_gpu_memory == nullptr);
|
||||
|
||||
g_gpu_memory->SetAllocatedRange(vaddr, size);
|
||||
}
|
||||
|
||||
void GpuMemoryFree(GraphicContext* ctx, uint64_t vaddr, uint64_t size)
|
||||
{
|
||||
EXIT_IF(g_gpu_memory == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
g_gpu_memory->Free(ctx, vaddr, size);
|
||||
}
|
||||
|
||||
void* GpuMemoryGetObject(GraphicContext* ctx, uint64_t vaddr, uint64_t size, const GpuObject& info)
|
||||
{
|
||||
EXIT_IF(g_gpu_memory == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
return g_gpu_memory->GetObject(ctx, &vaddr, &size, 1, info);
|
||||
}
|
||||
|
||||
void* GpuMemoryGetObject(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, const GpuObject& info)
|
||||
{
|
||||
EXIT_IF(g_gpu_memory == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
return g_gpu_memory->GetObject(ctx, vaddr, size, vaddr_num, info);
|
||||
}
|
||||
|
||||
void GpuMemoryResetHash(GraphicContext* ctx, uint64_t vaddr, uint64_t size, GpuMemoryObjectType type)
|
||||
{
|
||||
EXIT_IF(g_gpu_memory == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
g_gpu_memory->ResetHash(ctx, &vaddr, &size, 1, type);
|
||||
}
|
||||
|
||||
void GpuMemoryDbgDump()
|
||||
{
|
||||
EXIT_IF(g_gpu_memory == nullptr);
|
||||
|
||||
g_gpu_memory->DbgDump();
|
||||
}
|
||||
|
||||
void GpuMemoryFlush(GraphicContext* ctx)
|
||||
{
|
||||
EXIT_IF(g_gpu_memory == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
// update vulkan objects after CPU-drawing
|
||||
g_gpu_memory->Flush(ctx);
|
||||
}
|
||||
|
||||
void GpuMemoryFrameDone()
|
||||
{
|
||||
EXIT_IF(g_gpu_memory == nullptr);
|
||||
|
||||
g_gpu_memory->FrameDone();
|
||||
}
|
||||
|
||||
void GpuMemoryWriteBack(GraphicContext* ctx)
|
||||
{
|
||||
EXIT_IF(g_gpu_memory == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
// update CPU memory after GPU-drawing
|
||||
g_gpu_memory->WriteBack(ctx);
|
||||
}
|
||||
|
||||
bool VulkanAllocate(GraphicContext* ctx, VulkanMemory* mem)
|
||||
{
|
||||
static std::atomic<uint64_t> seq = 0;
|
||||
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(mem->memory != nullptr);
|
||||
EXIT_IF(mem->requirements.size == 0);
|
||||
|
||||
VkPhysicalDeviceMemoryProperties memory_properties {};
|
||||
vkGetPhysicalDeviceMemoryProperties(ctx->physical_device, &memory_properties);
|
||||
|
||||
uint32_t index = 0;
|
||||
for (; index < memory_properties.memoryTypeCount; index++)
|
||||
{
|
||||
if ((mem->requirements.memoryTypeBits & (static_cast<uint32_t>(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 = ++seq;
|
||||
|
||||
return (vkAllocateMemory(ctx->device, &alloc_info, nullptr, &mem->memory) == VK_SUCCESS);
|
||||
}
|
||||
|
||||
void VulkanFree(GraphicContext* ctx, VulkanMemory* mem)
|
||||
{
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
|
||||
vkFreeMemory(ctx->device, mem->memory, nullptr);
|
||||
|
||||
mem->memory = nullptr;
|
||||
}
|
||||
|
||||
void VulkanMapMemory(GraphicContext* ctx, VulkanMemory* mem, void** data)
|
||||
{
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(data == nullptr);
|
||||
|
||||
vkMapMemory(ctx->device, mem->memory, mem->offset, mem->requirements.size, 0, data);
|
||||
}
|
||||
|
||||
void VulkanUnmapMemory(GraphicContext* ctx, VulkanMemory* mem)
|
||||
{
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
|
||||
vkUnmapMemory(ctx->device, mem->memory);
|
||||
}
|
||||
|
||||
void VulkanBindImageMemory(GraphicContext* ctx, TextureVulkanImage* image, VulkanMemory* mem)
|
||||
{
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(image == nullptr);
|
||||
|
||||
vkBindImageMemory(ctx->device, image->image, mem->memory, mem->offset);
|
||||
}
|
||||
|
||||
void VulkanBindImageMemory(GraphicContext* ctx, VideoOutVulkanImage* image, VulkanMemory* mem)
|
||||
{
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(image == nullptr);
|
||||
|
||||
vkBindImageMemory(ctx->device, image->image, mem->memory, mem->offset);
|
||||
}
|
||||
|
||||
void VulkanBindImageMemory(GraphicContext* ctx, DepthStencilVulkanImage* image, VulkanMemory* mem)
|
||||
{
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(image == nullptr);
|
||||
|
||||
vkBindImageMemory(ctx->device, image->image, mem->memory, mem->offset);
|
||||
}
|
||||
|
||||
void VulkanBindBufferMemory(GraphicContext* ctx, VulkanBuffer* buffer, VulkanMemory* mem)
|
||||
{
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(buffer == nullptr);
|
||||
|
||||
vkBindBufferMemory(ctx->device, buffer->buffer, mem->memory, mem->offset);
|
||||
}
|
||||
|
||||
void GpuMemoryRegisterOwner(uint32_t* owner_handle, const char* name)
|
||||
{
|
||||
EXIT_IF(g_gpu_resources == nullptr);
|
||||
EXIT_IF(owner_handle == nullptr);
|
||||
EXIT_IF(name == nullptr);
|
||||
|
||||
*owner_handle = g_gpu_resources->AddOwner(String::FromUtf8(name));
|
||||
}
|
||||
|
||||
void GpuMemoryRegisterResource(uint32_t* resource_handle, uint32_t owner_handle, const void* memory, size_t size, const char* name,
|
||||
uint32_t type, uint64_t user_data)
|
||||
{
|
||||
EXIT_IF(g_gpu_resources == nullptr);
|
||||
EXIT_IF(resource_handle == nullptr);
|
||||
EXIT_IF(name == nullptr);
|
||||
|
||||
*resource_handle =
|
||||
g_gpu_resources->AddResource(owner_handle, reinterpret_cast<uint64_t>(memory), size, String::FromUtf8(name), type, user_data);
|
||||
}
|
||||
|
||||
void GpuMemoryUnregisterAllResourcesForOwner(uint32_t owner_handle)
|
||||
{
|
||||
EXIT_IF(g_gpu_resources == nullptr);
|
||||
|
||||
g_gpu_resources->DeleteResources(owner_handle);
|
||||
}
|
||||
|
||||
void GpuMemoryUnregisterOwnerAndResources(uint32_t owner_handle)
|
||||
{
|
||||
EXIT_IF(g_gpu_resources == nullptr);
|
||||
|
||||
g_gpu_resources->DeleteOwner(owner_handle);
|
||||
}
|
||||
|
||||
void GpuMemoryUnregisterResource(uint32_t resource_handle)
|
||||
{
|
||||
EXIT_IF(g_gpu_resources == nullptr);
|
||||
|
||||
g_gpu_resources->DeleteResource(resource_handle);
|
||||
}
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
@@ -5,11 +5,11 @@
|
||||
#include "Kyty/Core/String.h"
|
||||
|
||||
#include "Emulator/Config.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/GraphicsRender.h"
|
||||
#include "Emulator/Graphics/GraphicsRun.h"
|
||||
#include "Emulator/Graphics/HardwareContext.h"
|
||||
#include "Emulator/Graphics/Label.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Objects/Label.h"
|
||||
#include "Emulator/Graphics/Pm4.h"
|
||||
#include "Emulator/Graphics/Tile.h"
|
||||
#include "Emulator/Graphics/VideoOut.h"
|
||||
|
||||
@@ -6,20 +6,21 @@
|
||||
#include "Kyty/Math/Rand.h"
|
||||
|
||||
#include "Emulator/Config.h"
|
||||
#include "Emulator/Graphics/DepthStencilBuffer.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/GraphicContext.h"
|
||||
#include "Emulator/Graphics/HardwareContext.h"
|
||||
#include "Emulator/Graphics/IndexBuffer.h"
|
||||
#include "Emulator/Graphics/Label.h"
|
||||
#include "Emulator/Graphics/Objects/DepthStencilBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Objects/IndexBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/Label.h"
|
||||
#include "Emulator/Graphics/Objects/RenderTexture.h"
|
||||
#include "Emulator/Graphics/Objects/StorageBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/Texture.h"
|
||||
#include "Emulator/Graphics/Objects/VertexBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/VideoOutBuffer.h"
|
||||
#include "Emulator/Graphics/Shader.h"
|
||||
#include "Emulator/Graphics/StorageBuffer.h"
|
||||
#include "Emulator/Graphics/Texture.h"
|
||||
#include "Emulator/Graphics/Tile.h"
|
||||
#include "Emulator/Graphics/Utils.h"
|
||||
#include "Emulator/Graphics/VertexBuffer.h"
|
||||
#include "Emulator/Graphics/VideoOut.h"
|
||||
#include "Emulator/Graphics/VideoOutBuffer.h"
|
||||
#include "Emulator/Graphics/Window.h"
|
||||
#include "Emulator/Kernel/EventQueue.h"
|
||||
#include "Emulator/Kernel/Pthread.h"
|
||||
@@ -111,7 +112,7 @@ public:
|
||||
void DeleteAllPipelines();
|
||||
|
||||
private:
|
||||
static constexpr uint32_t MAX_PIPELINES = 16;
|
||||
static constexpr uint32_t MAX_PIPELINES = 32;
|
||||
|
||||
struct Pipeline
|
||||
{
|
||||
@@ -168,11 +169,10 @@ public:
|
||||
void Free(VulkanDescriptorSet* set);
|
||||
|
||||
VulkanDescriptorSet* GetDescriptor(Stage stage, int storage_buffers_num, VulkanBuffer** storage_buffers, int textures2d_sampled_num,
|
||||
TextureVulkanImage** textures2d_sampled, int textures2d_storage_num,
|
||||
TextureVulkanImage** textures2d_storage, int samplers_num, uint64_t* samplers, int gds_buffers_num,
|
||||
VulkanBuffer** gds_buffers);
|
||||
VulkanImage** textures2d_sampled, int textures2d_storage_num, VulkanImage** textures2d_storage,
|
||||
int samplers_num, uint64_t* samplers, int gds_buffers_num, VulkanBuffer** gds_buffers);
|
||||
void FreeDescriptor(VulkanBuffer* buffer);
|
||||
void FreeDescriptor(TextureVulkanImage* image);
|
||||
void FreeDescriptor(VulkanImage* image);
|
||||
|
||||
private:
|
||||
struct Set
|
||||
@@ -241,8 +241,8 @@ public:
|
||||
KYTY_CLASS_NO_COPY(FramebufferCache);
|
||||
|
||||
VulkanFramebuffer* CreateFramebuffer(RenderColorInfo* color, RenderDepthInfo* depth);
|
||||
void FreeFramebuffer(VideoOutVulkanImage* image);
|
||||
void FreeFramebuffer(DepthStencilVulkanImage* image);
|
||||
void FreeFramebufferByColor(VulkanImage* image);
|
||||
void FreeFramebufferByDepth(DepthStencilVulkanImage* image);
|
||||
|
||||
private:
|
||||
VideoOutVulkanImage* CreateDummyBuffer(VkFormat format, uint32_t width, uint32_t height);
|
||||
@@ -349,13 +349,25 @@ struct RenderDepthInfo
|
||||
VkStencilOpState stencil_front = {};
|
||||
VkStencilOpState stencil_back = {};
|
||||
DepthStencilVulkanImage* vulkan_buffer = nullptr;
|
||||
uint64_t vaddr[3] = {};
|
||||
uint64_t size[3] = {};
|
||||
int vaddr_num = 0;
|
||||
};
|
||||
|
||||
enum class RenderColorType
|
||||
{
|
||||
NoColorOutput,
|
||||
DisplayBuffer,
|
||||
OffscreenBuffer,
|
||||
RenderTexture,
|
||||
};
|
||||
|
||||
struct RenderColorInfo
|
||||
{
|
||||
VideoOutVulkanImage* vulkan_buffer = nullptr;
|
||||
uint64_t base_addr = 0;
|
||||
uint64_t buffer_size = 0;
|
||||
RenderColorType type = RenderColorType::NoColorOutput;
|
||||
VulkanImage* vulkan_buffer = nullptr;
|
||||
uint64_t base_addr = 0;
|
||||
uint64_t buffer_size = 0;
|
||||
};
|
||||
|
||||
class CommandPool
|
||||
@@ -550,7 +562,7 @@ static void z_check(const DepthRenderTarget& z)
|
||||
EXIT_NOT_IMPLEMENTED(z.z_info.format != 0x00000003);
|
||||
EXIT_NOT_IMPLEMENTED(z.z_info.tile_mode_index != (Config::IsNeo() ? 0x00000002 : 0));
|
||||
EXIT_NOT_IMPLEMENTED(z.z_info.num_samples != 0x00000000);
|
||||
EXIT_NOT_IMPLEMENTED(z.z_info.tile_surface_enable != true);
|
||||
// EXIT_NOT_IMPLEMENTED(z.z_info.tile_surface_enable != true);
|
||||
EXIT_NOT_IMPLEMENTED(z.z_info.expclear_enabled != false);
|
||||
EXIT_NOT_IMPLEMENTED(z.z_info.zrange_precision != 0x00000001);
|
||||
}
|
||||
@@ -594,11 +606,11 @@ static void z_check(const DepthRenderTarget& z)
|
||||
EXIT_NOT_IMPLEMENTED(z.z_write_base_addr == 0);
|
||||
EXIT_NOT_IMPLEMENTED(z.stencil_info.format != 0 && z.stencil_write_base_addr == 0);
|
||||
// EXIT_NOT_IMPLEMENTED(z.pitch_div8_minus1 != 0x000000ff);
|
||||
EXIT_NOT_IMPLEMENTED(z.height_div8_minus1 != 0x0000008f);
|
||||
// EXIT_NOT_IMPLEMENTED(z.height_div8_minus1 != 0x0000008f);
|
||||
// EXIT_NOT_IMPLEMENTED(z.slice_div64_minus1 != 0x00008fff);
|
||||
EXIT_NOT_IMPLEMENTED(z.htile_data_base_addr == 0);
|
||||
EXIT_NOT_IMPLEMENTED(z.width != 0x00000780);
|
||||
EXIT_NOT_IMPLEMENTED(z.height != 0x00000438);
|
||||
// EXIT_NOT_IMPLEMENTED(z.htile_data_base_addr == 0);
|
||||
// EXIT_NOT_IMPLEMENTED(z.width != 0x00000780);
|
||||
// EXIT_NOT_IMPLEMENTED(z.height != 0x00000438);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1142,7 +1154,7 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* color, R
|
||||
(color->vulkan_buffer->extent.width != depth->vulkan_buffer->extent.width ||
|
||||
color->vulkan_buffer->extent.height != depth->vulkan_buffer->extent.height));
|
||||
|
||||
VideoOutVulkanImage* vulkan_buffer =
|
||||
VulkanImage* vulkan_buffer =
|
||||
(with_color ? color->vulkan_buffer
|
||||
: CreateDummyBuffer(VK_FORMAT_B8G8R8A8_SRGB, depth->vulkan_buffer->extent.width, depth->vulkan_buffer->extent.height));
|
||||
|
||||
@@ -1247,7 +1259,7 @@ VulkanFramebuffer* FramebufferCache::CreateFramebuffer(RenderColorInfo* color, R
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
void FramebufferCache::FreeFramebuffer(VideoOutVulkanImage* image)
|
||||
void FramebufferCache::FreeFramebufferByColor(VulkanImage* image)
|
||||
{
|
||||
EXIT_IF(g_render_ctx == nullptr);
|
||||
EXIT_IF(image == nullptr);
|
||||
@@ -1277,7 +1289,7 @@ void FramebufferCache::FreeFramebuffer(VideoOutVulkanImage* image)
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferCache::FreeFramebuffer(DepthStencilVulkanImage* image)
|
||||
void FramebufferCache::FreeFramebufferByDepth(DepthStencilVulkanImage* image)
|
||||
{
|
||||
EXIT_IF(g_render_ctx == nullptr);
|
||||
EXIT_IF(image == nullptr);
|
||||
@@ -1328,6 +1340,7 @@ VideoOutVulkanImage* FramebufferCache::CreateDummyBuffer(VkFormat format, uint32
|
||||
vk_obj->format = format;
|
||||
vk_obj->image = nullptr;
|
||||
vk_obj->image_view = nullptr;
|
||||
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
VkImageCreateInfo image_info {};
|
||||
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
@@ -1341,7 +1354,7 @@ VideoOutVulkanImage* FramebufferCache::CreateDummyBuffer(VkFormat format, uint32
|
||||
image_info.arrayLayers = 1;
|
||||
image_info.format = vk_obj->format;
|
||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
image_info.initialLayout = vk_obj->layout;
|
||||
image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
@@ -2460,8 +2473,8 @@ void DescriptorCache::Free(VulkanDescriptorSet* set)
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, int storage_buffers_num, VulkanBuffer** storage_buffers,
|
||||
int textures2d_sampled_num, TextureVulkanImage** textures2d_sampled,
|
||||
int textures2d_storage_num, TextureVulkanImage** textures2d_storage, int samplers_num,
|
||||
int textures2d_sampled_num, VulkanImage** textures2d_sampled,
|
||||
int textures2d_storage_num, VulkanImage** textures2d_storage, int samplers_num,
|
||||
uint64_t* samplers, int gds_buffers_num, VulkanBuffer** gds_buffers)
|
||||
{
|
||||
EXIT_IF(storage_buffers_num < 0 || storage_buffers_num > BUFFERS_MAX);
|
||||
@@ -2736,7 +2749,7 @@ void DescriptorCache::FreeDescriptor(VulkanBuffer* buffer)
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorCache::FreeDescriptor(TextureVulkanImage* image)
|
||||
void DescriptorCache::FreeDescriptor(VulkanImage* image)
|
||||
{
|
||||
EXIT_IF(image == nullptr);
|
||||
|
||||
@@ -2790,12 +2803,17 @@ VkDescriptorSetLayout DescriptorCache::GetDescriptorSetLayout(Stage stage, int s
|
||||
|
||||
void DeleteFramebuffer(VideoOutVulkanImage* image)
|
||||
{
|
||||
g_render_ctx->GetFramebufferCache()->FreeFramebuffer(image);
|
||||
g_render_ctx->GetFramebufferCache()->FreeFramebufferByColor(image);
|
||||
}
|
||||
|
||||
void DeleteFramebuffer(RenderTextureVulkanImage* image)
|
||||
{
|
||||
g_render_ctx->GetFramebufferCache()->FreeFramebufferByColor(image);
|
||||
}
|
||||
|
||||
void DeleteFramebuffer(DepthStencilVulkanImage* image)
|
||||
{
|
||||
g_render_ctx->GetFramebufferCache()->FreeFramebuffer(image);
|
||||
g_render_ctx->GetFramebufferCache()->FreeFramebufferByDepth(image);
|
||||
}
|
||||
|
||||
void DeleteDescriptor(VulkanBuffer* buffer)
|
||||
@@ -2808,6 +2826,11 @@ void DeleteDescriptor(TextureVulkanImage* image)
|
||||
g_render_ctx->GetDescriptorCache()->FreeDescriptor(image);
|
||||
}
|
||||
|
||||
void DeleteDescriptor(RenderTextureVulkanImage* image)
|
||||
{
|
||||
g_render_ctx->GetDescriptorCache()->FreeDescriptor(image);
|
||||
}
|
||||
|
||||
static void FindRenderDepthInfo(const HardwareContext& hw, RenderDepthInfo* r)
|
||||
{
|
||||
EXIT_IF(r == nullptr);
|
||||
@@ -2817,17 +2840,33 @@ static void FindRenderDepthInfo(const HardwareContext& hw, RenderDepthInfo* r)
|
||||
const auto& rc = hw.GetRenderControl();
|
||||
const auto& dc = hw.GetDepthControl();
|
||||
|
||||
uint32_t size = 0;
|
||||
uint32_t stencil_size = 0;
|
||||
uint32_t htile_size = 0;
|
||||
uint32_t depth_size = 0;
|
||||
uint32_t pitch = 0;
|
||||
|
||||
if (z.z_info.format == 3)
|
||||
{
|
||||
size = (z.slice_div64_minus1 + 1) * 64 * 4;
|
||||
} else if (z.z_info.format == 1)
|
||||
{
|
||||
size = (z.slice_div64_minus1 + 1) * 64 * 2;
|
||||
}
|
||||
|
||||
bool htile = z.z_info.tile_surface_enable;
|
||||
|
||||
TileGetDepthSize(z.width, z.height, z.z_info.format, z.stencil_info.format, htile, neo, &stencil_size, &htile_size, &depth_size,
|
||||
&pitch);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(pitch != 0 && (z.pitch_div8_minus1 + 1) * 8 != pitch);
|
||||
if (pitch == 0)
|
||||
{
|
||||
depth_size = size;
|
||||
} else
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(depth_size != size);
|
||||
EXIT_NOT_IMPLEMENTED((z.pitch_div8_minus1 + 1) * 8 != pitch);
|
||||
}
|
||||
|
||||
switch (z.z_info.format * 2 + z.stencil_info.format)
|
||||
{
|
||||
@@ -2877,117 +2916,170 @@ static void FindRenderDepthInfo(const HardwareContext& hw, RenderDepthInfo* r)
|
||||
{
|
||||
DepthStencilBufferObject vulkan_buffer_info(r->format, r->width, r->height, htile, neo);
|
||||
|
||||
uint64_t vaddr[3] = {};
|
||||
uint64_t size[3] = {};
|
||||
int vaddr_num = 0;
|
||||
r->vaddr_num = 0;
|
||||
|
||||
if (r->depth_buffer_size > 0)
|
||||
{
|
||||
vaddr[vaddr_num] = r->depth_buffer_vaddr;
|
||||
size[vaddr_num] = r->depth_buffer_size;
|
||||
vaddr_num++;
|
||||
r->vaddr[r->vaddr_num] = r->depth_buffer_vaddr;
|
||||
r->size[r->vaddr_num] = r->depth_buffer_size;
|
||||
r->vaddr_num++;
|
||||
}
|
||||
|
||||
if (r->stencil_buffer_size > 0)
|
||||
{
|
||||
vaddr[vaddr_num] = r->stencil_buffer_vaddr;
|
||||
size[vaddr_num] = r->stencil_buffer_size;
|
||||
vaddr_num++;
|
||||
r->vaddr[r->vaddr_num] = r->stencil_buffer_vaddr;
|
||||
r->size[r->vaddr_num] = r->stencil_buffer_size;
|
||||
r->vaddr_num++;
|
||||
}
|
||||
|
||||
if (r->htile_buffer_size > 0)
|
||||
{
|
||||
vaddr[vaddr_num] = r->htile_buffer_vaddr;
|
||||
size[vaddr_num] = r->htile_buffer_size;
|
||||
vaddr_num++;
|
||||
r->vaddr[r->vaddr_num] = r->htile_buffer_vaddr;
|
||||
r->size[r->vaddr_num] = r->htile_buffer_size;
|
||||
r->vaddr_num++;
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(vaddr_num == 0);
|
||||
EXIT_NOT_IMPLEMENTED(r->vaddr_num == 0);
|
||||
|
||||
r->vulkan_buffer = static_cast<DepthStencilVulkanImage*>(
|
||||
GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), vaddr, size, vaddr_num, vulkan_buffer_info));
|
||||
GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), r->vaddr, r->size, r->vaddr_num, vulkan_buffer_info));
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(r->vulkan_buffer == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
static void FindRenderColorInfo(const HardwareContext& hw, RenderColorInfo* r)
|
||||
{
|
||||
EXIT_IF(r == nullptr);
|
||||
|
||||
const auto& rt = hw.GetRenderTargets(0);
|
||||
const auto& rt = hw.GetRenderTargets(0);
|
||||
auto mask = hw.GetRenderTargetMask();
|
||||
|
||||
if (rt.base_addr != 0)
|
||||
{
|
||||
auto width = rt.width;
|
||||
auto height = rt.height;
|
||||
auto pitch = (rt.pitch_div8_minus1 + 1) * 8;
|
||||
auto size = (rt.slice_div64_minus1 + 1) * 64 * 4;
|
||||
bool tile = false;
|
||||
uint32_t format = 0;
|
||||
bool render_to_texture = false;
|
||||
|
||||
if (rt.tile_mode == 0x8)
|
||||
{
|
||||
tile = false;
|
||||
} else if (rt.tile_mode == 0xa)
|
||||
{
|
||||
tile = true;
|
||||
} else if (rt.tile_mode == 0xd)
|
||||
{
|
||||
tile = true;
|
||||
render_to_texture = true;
|
||||
} else
|
||||
{
|
||||
EXIT("unknown tile mode: %u\n", rt.tile_mode);
|
||||
}
|
||||
|
||||
if (render_to_texture)
|
||||
{
|
||||
EXIT("not implemented");
|
||||
} else
|
||||
{
|
||||
if (rt.format == 0xa && rt.channel_type == 0x6 && rt.channel_order == 0x1)
|
||||
{
|
||||
format = 0x80000000;
|
||||
} else
|
||||
{
|
||||
EXIT("unknown format");
|
||||
}
|
||||
|
||||
auto video_image = VideoOut::VideoOutGetImage(rt.base_addr);
|
||||
if (video_image.image == nullptr)
|
||||
{
|
||||
// Offscreen buffer
|
||||
VideoOutBufferObject vulkan_buffer_info(format, width, height, tile, Config::IsNeo(), pitch);
|
||||
auto* buffer_vulkan = static_cast<Graphics::VideoOutVulkanImage*>(
|
||||
Graphics::GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), rt.base_addr, size, vulkan_buffer_info));
|
||||
EXIT_NOT_IMPLEMENTED(buffer_vulkan == nullptr);
|
||||
r->base_addr = rt.base_addr;
|
||||
r->vulkan_buffer = buffer_vulkan;
|
||||
r->buffer_size = size;
|
||||
} else
|
||||
{
|
||||
// Display buffer
|
||||
EXIT_NOT_IMPLEMENTED(video_image.buffer_size != size);
|
||||
EXIT_NOT_IMPLEMENTED(video_image.buffer_pitch != pitch);
|
||||
r->base_addr = rt.base_addr;
|
||||
r->vulkan_buffer = video_image.image;
|
||||
r->buffer_size = video_image.buffer_size;
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (rt.base_addr == 0 || mask == 0)
|
||||
{
|
||||
// No color output
|
||||
r->type = RenderColorType::NoColorOutput;
|
||||
r->base_addr = 0;
|
||||
r->vulkan_buffer = nullptr;
|
||||
r->buffer_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
auto width = rt.width;
|
||||
auto height = rt.height;
|
||||
auto pitch = (rt.pitch_div8_minus1 + 1) * 8;
|
||||
auto size = (rt.slice_div64_minus1 + 1) * 64 * 4;
|
||||
bool tile = false;
|
||||
uint32_t format = 0;
|
||||
bool render_to_texture = false;
|
||||
|
||||
if (rt.tile_mode == 0x8)
|
||||
{
|
||||
tile = false;
|
||||
} else if (rt.tile_mode == 0xa)
|
||||
{
|
||||
tile = true;
|
||||
} else if (rt.tile_mode == 0xd || rt.tile_mode == 0xe)
|
||||
{
|
||||
tile = true;
|
||||
render_to_texture = true;
|
||||
} else
|
||||
{
|
||||
EXIT("unknown tile mode: %u\n", rt.tile_mode);
|
||||
}
|
||||
|
||||
if (render_to_texture)
|
||||
{
|
||||
if (rt.format == 0xa && rt.channel_type == 0x0 && rt.channel_order == 0x0)
|
||||
{
|
||||
// Render to texture
|
||||
RenderTextureObject vulkan_buffer_info(RenderTextureFormat::R8G8B8A8Unorm, width, height, tile, rt.neo_mode, pitch);
|
||||
auto* buffer_vulkan = static_cast<Graphics::RenderTextureVulkanImage*>(
|
||||
Graphics::GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), rt.base_addr, size, vulkan_buffer_info));
|
||||
EXIT_NOT_IMPLEMENTED(buffer_vulkan == nullptr);
|
||||
r->type = RenderColorType::RenderTexture;
|
||||
r->base_addr = rt.base_addr;
|
||||
r->vulkan_buffer = buffer_vulkan;
|
||||
r->buffer_size = size;
|
||||
} else
|
||||
{
|
||||
EXIT("unknown format");
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (rt.format == 0xa && rt.channel_type == 0x6 && rt.channel_order == 0x1)
|
||||
{
|
||||
format = 0x80000000;
|
||||
} else
|
||||
{
|
||||
EXIT("unknown format");
|
||||
}
|
||||
|
||||
auto video_image = VideoOut::VideoOutGetImage(rt.base_addr);
|
||||
if (video_image.image == nullptr)
|
||||
{
|
||||
// Offscreen buffer
|
||||
VideoOutBufferObject vulkan_buffer_info(format, width, height, tile, Config::IsNeo(), pitch);
|
||||
auto* buffer_vulkan = static_cast<Graphics::VideoOutVulkanImage*>(
|
||||
Graphics::GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), rt.base_addr, size, vulkan_buffer_info));
|
||||
EXIT_NOT_IMPLEMENTED(buffer_vulkan == nullptr);
|
||||
r->type = RenderColorType::OffscreenBuffer;
|
||||
r->base_addr = rt.base_addr;
|
||||
r->vulkan_buffer = buffer_vulkan;
|
||||
r->buffer_size = size;
|
||||
} else
|
||||
{
|
||||
// Display buffer
|
||||
EXIT_NOT_IMPLEMENTED(video_image.buffer_size != size);
|
||||
EXIT_NOT_IMPLEMENTED(video_image.buffer_pitch != pitch);
|
||||
r->type = RenderColorType::DisplayBuffer;
|
||||
r->base_addr = rt.base_addr;
|
||||
r->vulkan_buffer = video_image.image;
|
||||
r->buffer_size = video_image.buffer_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void InvalidateMemoryObject(const RenderColorInfo& r)
|
||||
{
|
||||
GpuMemoryResetHash(g_render_ctx->GetGraphicCtx(), r.base_addr, r.buffer_size, GpuMemoryObjectType::VideoOutBuffer);
|
||||
bool with_color = (r.vulkan_buffer != nullptr);
|
||||
|
||||
if (with_color)
|
||||
{
|
||||
if (r.type == RenderColorType::RenderTexture)
|
||||
{
|
||||
GpuMemoryResetHash(g_render_ctx->GetGraphicCtx(), &r.base_addr, &r.buffer_size, 1, GpuMemoryObjectType::RenderTexture);
|
||||
} else if (r.type == RenderColorType::DisplayBuffer || r.type == RenderColorType::OffscreenBuffer)
|
||||
{
|
||||
GpuMemoryResetHash(g_render_ctx->GetGraphicCtx(), &r.base_addr, &r.buffer_size, 1, GpuMemoryObjectType::VideoOutBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void InvalidateMemoryObject(const RenderDepthInfo& r)
|
||||
{
|
||||
bool with_depth = (r.format != VK_FORMAT_UNDEFINED && r.vulkan_buffer != nullptr);
|
||||
|
||||
if (with_depth)
|
||||
{
|
||||
GpuMemoryResetHash(g_render_ctx->GetGraphicCtx(), r.vaddr, r.size, r.vaddr_num, GpuMemoryObjectType::DepthStencilBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
static RenderTextureVulkanImage* FindRenderTexture(uint64_t vaddr, uint64_t size)
|
||||
{
|
||||
auto objects = GpuMemoryFindObjects(vaddr, size);
|
||||
|
||||
for (const auto& obj: objects)
|
||||
{
|
||||
if (obj.type == GpuMemoryObjectType::RenderTexture)
|
||||
{
|
||||
return static_cast<RenderTextureVulkanImage*>(obj.obj);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void PrepareStorageBuffers(const ShaderStorageResources& storage_buffers, VulkanBuffer** buffers, uint32_t** sgprs)
|
||||
@@ -3026,7 +3118,7 @@ static void PrepareStorageBuffers(const ShaderStorageResources& storage_buffers,
|
||||
|
||||
StorageBufferGpuObject buf_info(stride, num_records, read_only);
|
||||
|
||||
auto* buf = static_cast<VulkanBuffer*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), addr, size, buf_info));
|
||||
auto* buf = static_cast<VulkanBuffer*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), addr, size, buf_info));
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(buf == nullptr);
|
||||
|
||||
@@ -3046,7 +3138,7 @@ static void PrepareStorageBuffers(const ShaderStorageResources& storage_buffers,
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
static void PrepareTextures(const ShaderTextureResources& textures, TextureVulkanImage** images, uint32_t** sgprs, bool with_sampler)
|
||||
static void PrepareTextures(const ShaderTextureResources& textures, VulkanImage** images, uint32_t** sgprs, bool with_sampler)
|
||||
{
|
||||
EXIT_IF(images == nullptr);
|
||||
EXIT_IF(sgprs == nullptr);
|
||||
@@ -3059,7 +3151,7 @@ static void PrepareTextures(const ShaderTextureResources& textures, TextureVulka
|
||||
EXIT_NOT_IMPLEMENTED(r.Base() == 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.MinLod() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.Dfmt() != 10 && r.Dfmt() != 37);
|
||||
EXIT_NOT_IMPLEMENTED(r.Nfmt() != 9);
|
||||
EXIT_NOT_IMPLEMENTED(r.Nfmt() != 9 && r.Nfmt() != 0);
|
||||
// EXIT_NOT_IMPLEMENTED(r.Width() != 511);
|
||||
// EXIT_NOT_IMPLEMENTED(r.Height() != 511);
|
||||
EXIT_NOT_IMPLEMENTED(r.PerfMod() != 7 && r.PerfMod() != 0);
|
||||
@@ -3070,7 +3162,7 @@ static void PrepareTextures(const ShaderTextureResources& textures, TextureVulka
|
||||
// EXIT_NOT_IMPLEMENTED(r.DstSelW() != 7);
|
||||
EXIT_NOT_IMPLEMENTED(r.BaseLevel() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.LastLevel() != 0 && r.LastLevel() != 9);
|
||||
EXIT_NOT_IMPLEMENTED(!(r.TilingIdx() == 8 || r.TilingIdx() == 13));
|
||||
EXIT_NOT_IMPLEMENTED(!(r.TilingIdx() == 8 || r.TilingIdx() == 13 || r.TilingIdx() == 14));
|
||||
EXIT_NOT_IMPLEMENTED(!(r.LastLevel() == 0 && r.Pow2Pad() == false) && !(r.LastLevel() == 9 && r.Pow2Pad() == true));
|
||||
EXIT_NOT_IMPLEMENTED(r.Type() != 9);
|
||||
EXIT_NOT_IMPLEMENTED(r.Depth() != 0);
|
||||
@@ -3089,17 +3181,22 @@ static void PrepareTextures(const ShaderTextureResources& textures, TextureVulka
|
||||
auto height = r.Height() + 1;
|
||||
auto pitch = r.Pitch() + 1;
|
||||
auto levels = r.LastLevel() - r.BaseLevel() + 1;
|
||||
bool tile = (r.TilingIdx() != 8);
|
||||
auto tile = r.TilingIdx();
|
||||
uint32_t swizzle = static_cast<uint32_t>(r.DstSelX()) | (static_cast<uint32_t>(r.DstSelY()) << 8u) |
|
||||
(static_cast<uint32_t>(r.DstSelZ()) << 16u) | (static_cast<uint32_t>(r.DstSelW()) << 24u);
|
||||
|
||||
TileGetTextureSize(r.Dfmt(), r.Nfmt(), width, height, pitch, levels, tile, neo, &size, nullptr, nullptr, nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(size == 0);
|
||||
|
||||
TextureObject vulkan_texture_info(r.Dfmt(), r.Nfmt(), width, height, pitch, levels, tile, neo, swizzle,
|
||||
(with_sampler ? TextureObject::TEXTURE_USAGE_SAMPLED : TextureObject::TEXTURE_USAGE_STORAGE));
|
||||
VulkanImage* tex = FindRenderTexture(addr, size);
|
||||
|
||||
auto* tex = static_cast<TextureVulkanImage*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), addr, size, vulkan_texture_info));
|
||||
if (tex == nullptr)
|
||||
{
|
||||
TextureObject vulkan_texture_info(r.Dfmt(), r.Nfmt(), width, height, pitch, levels, tile, neo, swizzle,
|
||||
(with_sampler ? TextureObject::TEXTURE_USAGE_SAMPLED : TextureObject::TEXTURE_USAGE_STORAGE));
|
||||
|
||||
tex = static_cast<TextureVulkanImage*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), addr, size, vulkan_texture_info));
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(tex == nullptr);
|
||||
|
||||
@@ -3205,11 +3302,11 @@ static void BindDescriptors(VkCommandBuffer vk_buffer, VkPipelineBindPoint pipel
|
||||
(!bind_params.textures2D_without_sampler && bind.textures2D.textures_num > DescriptorCache::TEXTURES_SAMPLED_MAX));
|
||||
EXIT_NOT_IMPLEMENTED(bind.samplers.samplers_num > DescriptorCache::SAMPLERS_MAX);
|
||||
|
||||
VulkanBuffer* storage_buffers[DescriptorCache::BUFFERS_MAX];
|
||||
TextureVulkanImage* textures2d_sampled[DescriptorCache::TEXTURES_SAMPLED_MAX];
|
||||
TextureVulkanImage* textures2d_storage[DescriptorCache::TEXTURES_STORAGE_MAX];
|
||||
uint64_t samplers[DescriptorCache::SAMPLERS_MAX];
|
||||
uint32_t sgprs[DescriptorCache::PUSH_CONSTANTS_MAX];
|
||||
VulkanBuffer* storage_buffers[DescriptorCache::BUFFERS_MAX];
|
||||
VulkanImage* textures2d_sampled[DescriptorCache::TEXTURES_SAMPLED_MAX];
|
||||
VulkanImage* textures2d_storage[DescriptorCache::TEXTURES_STORAGE_MAX];
|
||||
uint64_t samplers[DescriptorCache::SAMPLERS_MAX];
|
||||
uint32_t sgprs[DescriptorCache::PUSH_CONSTANTS_MAX];
|
||||
|
||||
uint32_t* sgprs_ptr = sgprs;
|
||||
|
||||
@@ -3343,7 +3440,8 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserCo
|
||||
uint64_t addr = b.addr;
|
||||
uint64_t size = b.stride * b.num_records;
|
||||
|
||||
auto* vertices = static_cast<VulkanBuffer*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), addr, size, VertexBufferGpuObject()));
|
||||
auto* vertices =
|
||||
static_cast<VulkanBuffer*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), addr, size, VertexBufferGpuObject()));
|
||||
|
||||
VkDeviceSize offset = 0;
|
||||
|
||||
@@ -3357,7 +3455,7 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserCo
|
||||
pipeline->additional_params->ps_bind, VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel);
|
||||
|
||||
VulkanBuffer* indices = static_cast<VulkanBuffer*>(
|
||||
GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(index_addr), index_size, IndexBufferGpuObject()));
|
||||
GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(index_addr), index_size, IndexBufferGpuObject()));
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(indices == nullptr);
|
||||
|
||||
@@ -3368,6 +3466,7 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserCo
|
||||
buffer->EndRenderPass();
|
||||
|
||||
InvalidateMemoryObject(color_info);
|
||||
InvalidateMemoryObject(depth_info);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
@@ -3448,7 +3547,8 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HardwareContext* ctx, Us
|
||||
uint64_t addr = b.addr;
|
||||
uint64_t size = b.stride * b.num_records;
|
||||
|
||||
auto* vertices = static_cast<VulkanBuffer*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), addr, size, VertexBufferGpuObject()));
|
||||
auto* vertices =
|
||||
static_cast<VulkanBuffer*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), addr, size, VertexBufferGpuObject()));
|
||||
|
||||
VkDeviceSize offset = 0;
|
||||
|
||||
@@ -3479,6 +3579,7 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HardwareContext* ctx, Us
|
||||
buffer->EndRenderPass();
|
||||
|
||||
InvalidateMemoryObject(color_info);
|
||||
InvalidateMemoryObject(depth_info);
|
||||
}
|
||||
|
||||
void GraphicsRenderDispatchDirect(CommandBuffer* buffer, HardwareContext* ctx, uint32_t thread_group_x, uint32_t thread_group_y,
|
||||
@@ -3535,6 +3636,43 @@ void GraphicsRenderMemoryBarrier(CommandBuffer* buffer)
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void GraphicsRenderRenderTextureBarrier(CommandBuffer* buffer, uint64_t vaddr, uint64_t size)
|
||||
{
|
||||
EXIT_IF(buffer == nullptr);
|
||||
EXIT_IF(buffer->IsInvalid());
|
||||
|
||||
Core::LockGuard lock(g_render_ctx->GetMutex());
|
||||
|
||||
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
|
||||
|
||||
VulkanImage* image = FindRenderTexture(vaddr, size);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(image == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(image->layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
VkImageMemoryBarrier image_memory_barrier {};
|
||||
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
image_memory_barrier.pNext = nullptr;
|
||||
image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
|
||||
image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||
image_memory_barrier.oldLayout = image->layout;
|
||||
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.image = image->image;
|
||||
image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
image_memory_barrier.subresourceRange.baseMipLevel = 0;
|
||||
image_memory_barrier.subresourceRange.levelCount = 1;
|
||||
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
|
||||
image_memory_barrier.subresourceRange.layerCount = 1;
|
||||
|
||||
vkCmdPipelineBarrier(vk_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1,
|
||||
&image_memory_barrier);
|
||||
|
||||
image->layout = image_memory_barrier.newLayout;
|
||||
}
|
||||
|
||||
void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint32_t* dst_gpu_addr, uint32_t value)
|
||||
{
|
||||
EXIT_IF(g_render_ctx == nullptr);
|
||||
@@ -3547,7 +3685,7 @@ void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint32_t* dst_gpu_add
|
||||
Graphics::LabelGpuObject label_info(value, nullptr, nullptr);
|
||||
|
||||
auto* label =
|
||||
static_cast<Label*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 4, label_info));
|
||||
static_cast<Label*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 4, label_info));
|
||||
|
||||
LabelSet(buffer, label);
|
||||
}
|
||||
@@ -3576,7 +3714,7 @@ void GraphicsRenderWriteAtEndOfPipeGds(CommandBuffer* buffer, uint32_t* dst_gpu_
|
||||
nullptr, args);
|
||||
|
||||
auto* label =
|
||||
static_cast<Label*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 4, label_info));
|
||||
static_cast<Label*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 4, label_info));
|
||||
|
||||
LabelSet(buffer, label);
|
||||
}
|
||||
@@ -3593,7 +3731,7 @@ void GraphicsRenderWriteAtEndOfPipe(CommandBuffer* buffer, uint64_t* dst_gpu_add
|
||||
Graphics::LabelGpuObject label_info(value, nullptr, nullptr);
|
||||
|
||||
auto* label =
|
||||
static_cast<Label*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 8, label_info));
|
||||
static_cast<Label*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 8, label_info));
|
||||
|
||||
LabelSet(buffer, label);
|
||||
}
|
||||
@@ -3623,7 +3761,7 @@ void GraphicsRenderWriteAtEndOfPipeClockCounter(CommandBuffer* buffer, uint64_t*
|
||||
nullptr, args);
|
||||
|
||||
auto* label =
|
||||
static_cast<Label*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 8, label_info));
|
||||
static_cast<Label*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 8, label_info));
|
||||
|
||||
LabelSet(buffer, label);
|
||||
}
|
||||
@@ -3648,7 +3786,7 @@ void GraphicsRenderWriteAtEndOfPipeWithWriteBack(CommandBuffer* buffer, uint64_t
|
||||
nullptr);
|
||||
|
||||
auto* label =
|
||||
static_cast<Label*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 8, label_info));
|
||||
static_cast<Label*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 8, label_info));
|
||||
|
||||
LabelSet(buffer, label);
|
||||
}
|
||||
@@ -3678,7 +3816,7 @@ void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBack(CommandBuffer* buffer,
|
||||
});
|
||||
|
||||
auto* label =
|
||||
static_cast<Label*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 8, label_info));
|
||||
static_cast<Label*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 8, label_info));
|
||||
|
||||
LabelSet(buffer, label);
|
||||
}
|
||||
@@ -3701,7 +3839,7 @@ void GraphicsRenderWriteAtEndOfPipeWithInterrupt(CommandBuffer* buffer, uint64_t
|
||||
});
|
||||
|
||||
auto* label =
|
||||
static_cast<Label*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 8, label_info));
|
||||
static_cast<Label*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 8, label_info));
|
||||
|
||||
LabelSet(buffer, label);
|
||||
}
|
||||
@@ -3743,7 +3881,7 @@ void GraphicsRenderWriteAtEndOfPipeWithInterruptWriteBackFlip(CommandBuffer* buf
|
||||
args);
|
||||
|
||||
auto* label =
|
||||
static_cast<Label*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 4, label_info));
|
||||
static_cast<Label*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 4, label_info));
|
||||
|
||||
LabelSet(buffer, label);
|
||||
}
|
||||
@@ -3776,7 +3914,7 @@ void GraphicsRenderWriteAtEndOfPipeWithFlip(CommandBuffer* buffer, uint32_t* dst
|
||||
nullptr, args);
|
||||
|
||||
auto* label =
|
||||
static_cast<Label*>(GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 4, label_info));
|
||||
static_cast<Label*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(dst_gpu_addr), 4, label_info));
|
||||
|
||||
LabelSet(buffer, label);
|
||||
}
|
||||
@@ -4069,6 +4207,31 @@ VulkanFramebuffer* CommandBuffer::BeginRenderPass(RenderColorInfo* color, Render
|
||||
render_pass_info.clearValueCount = with_depth ? 2 : 1;
|
||||
render_pass_info.pClearValues = clears;
|
||||
|
||||
if (with_color && color->vulkan_buffer->layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
|
||||
{
|
||||
VkImageMemoryBarrier image_memory_barrier {};
|
||||
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
image_memory_barrier.pNext = nullptr;
|
||||
image_memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||
image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
|
||||
image_memory_barrier.oldLayout = color->vulkan_buffer->layout;
|
||||
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.image = color->vulkan_buffer->image;
|
||||
image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
image_memory_barrier.subresourceRange.baseMipLevel = 0;
|
||||
image_memory_barrier.subresourceRange.levelCount = 1;
|
||||
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
|
||||
image_memory_barrier.subresourceRange.layerCount = 1;
|
||||
|
||||
vkCmdPipelineBarrier(buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1,
|
||||
&image_memory_barrier);
|
||||
|
||||
color->vulkan_buffer->layout = image_memory_barrier.newLayout;
|
||||
}
|
||||
|
||||
vkCmdBeginRenderPass(buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
return framebuffer;
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
void FlipWithInterrupt(uint32_t eop_event_type, uint32_t cache_action, void* dst_gpu_addr, uint32_t value);
|
||||
void WriteBack();
|
||||
void MemoryBarrier();
|
||||
void RenderTextureBarrier(uint64_t vaddr, uint64_t size);
|
||||
void DispatchDirect(uint32_t thread_group_x, uint32_t thread_group_y, uint32_t thread_group_z, uint32_t mode);
|
||||
void WaitFlipDone(uint32_t video_out_handle, uint32_t display_buffer_index);
|
||||
void TriggerEvent(uint32_t event_type, uint32_t event_index);
|
||||
@@ -1109,6 +1110,15 @@ void CommandProcessor::MemoryBarrier()
|
||||
GraphicsRenderMemoryBarrier(m_buffer[m_current_buffer]);
|
||||
}
|
||||
|
||||
void CommandProcessor::RenderTextureBarrier(uint64_t vaddr, uint64_t size)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
EXIT_IF(m_current_buffer < 0 || m_current_buffer >= VK_BUFFERS_NUM);
|
||||
|
||||
GraphicsRenderRenderTextureBarrier(m_buffer[m_current_buffer], vaddr, size);
|
||||
}
|
||||
|
||||
void CommandProcessor::TriggerEvent(uint32_t event_type, uint32_t event_index)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
@@ -1117,7 +1127,7 @@ void CommandProcessor::TriggerEvent(uint32_t event_type, uint32_t event_index)
|
||||
printf("\t event_type = 0x%08" PRIx32 "\n", event_type);
|
||||
printf("\t event_index = 0x%08" PRIx32 "\n", event_index);
|
||||
|
||||
if (event_type == 0x00000016 && event_index == 0x00000007)
|
||||
if ((event_type == 0x00000016 || event_type == 0x00000031) && event_index == 0x00000007)
|
||||
{
|
||||
MemoryBarrier();
|
||||
} else
|
||||
@@ -2192,25 +2202,42 @@ KYTY_CP_OP_PARSER(cp_op_acquire_mem)
|
||||
|
||||
uint32_t stall_mode = buffer[0] >> 31u;
|
||||
uint32_t cache_action = buffer[0] & 0x7fffffffu;
|
||||
uint32_t size_lo = buffer[1];
|
||||
uint64_t size_lo = buffer[1];
|
||||
uint32_t size_hi = buffer[2];
|
||||
uint32_t base_lo = buffer[3];
|
||||
uint64_t base_lo = buffer[3];
|
||||
uint32_t base_hi = buffer[4];
|
||||
uint32_t poll = buffer[5];
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(stall_mode != 1);
|
||||
EXIT_NOT_IMPLEMENTED(cache_action != 0x00C40000 && cache_action != 0x00400000);
|
||||
EXIT_NOT_IMPLEMENTED(size_lo != 1);
|
||||
EXIT_NOT_IMPLEMENTED(size_hi != 0);
|
||||
EXIT_NOT_IMPLEMENTED(base_lo != 0);
|
||||
EXIT_NOT_IMPLEMENTED(base_hi != 0);
|
||||
EXIT_NOT_IMPLEMENTED(poll != 10);
|
||||
|
||||
cp->MemoryBarrier();
|
||||
|
||||
if (cache_action == 0x00C40000)
|
||||
switch (cache_action)
|
||||
{
|
||||
cp->WriteBack();
|
||||
case 0x02003fc0:
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(size_lo == 0);
|
||||
EXIT_NOT_IMPLEMENTED(base_lo == 0);
|
||||
cp->RenderTextureBarrier(base_lo << 8u, size_lo << 8u);
|
||||
}
|
||||
break;
|
||||
case 0x00C40000:
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(size_lo != 1);
|
||||
EXIT_NOT_IMPLEMENTED(base_lo != 0);
|
||||
cp->MemoryBarrier();
|
||||
cp->WriteBack();
|
||||
}
|
||||
break;
|
||||
case 0x00400000:
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(size_lo != 1);
|
||||
EXIT_NOT_IMPLEMENTED(base_lo != 0);
|
||||
cp->MemoryBarrier();
|
||||
}
|
||||
break;
|
||||
default: EXIT("unknown barrier");
|
||||
}
|
||||
|
||||
return 6;
|
||||
|
||||
+4
-3
@@ -1,4 +1,4 @@
|
||||
#include "Emulator/Graphics/DepthStencilBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/DepthStencilBuffer.h"
|
||||
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
|
||||
@@ -37,6 +37,7 @@ void* DepthStencilBufferObject::Create(GraphicContext* ctx, const uint64_t* vadd
|
||||
vk_obj->format = pixel_format;
|
||||
vk_obj->image = nullptr;
|
||||
vk_obj->image_view = nullptr;
|
||||
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
VkImageCreateInfo image_info {};
|
||||
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
@@ -50,7 +51,7 @@ void* DepthStencilBufferObject::Create(GraphicContext* ctx, const uint64_t* vadd
|
||||
image_info.arrayLayers = 1;
|
||||
image_info.format = vk_obj->format;
|
||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
image_info.initialLayout = vk_obj->layout;
|
||||
image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
@@ -96,7 +97,7 @@ void* DepthStencilBufferObject::Create(GraphicContext* ctx, const uint64_t* vadd
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
|
||||
|
||||
UtilSetImageLayoutOptimal(vk_obj);
|
||||
UtilSetDepthLayoutOptimal(vk_obj);
|
||||
|
||||
return vk_obj;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,4 +1,4 @@
|
||||
#include "Emulator/Graphics/IndexBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/IndexBuffer.h"
|
||||
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#include "Emulator/Graphics/Label.h"
|
||||
#include "Emulator/Graphics/Objects/Label.h"
|
||||
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
#include "Kyty/Core/Threads.h"
|
||||
@@ -0,0 +1,211 @@
|
||||
#include "Emulator/Graphics/Objects/RenderTexture.h"
|
||||
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
|
||||
#include "Emulator/Graphics/GraphicContext.h"
|
||||
#include "Emulator/Graphics/GraphicsRender.h"
|
||||
//#include "Emulator/Graphics/Tile.h"
|
||||
#include "Emulator/Graphics/Utils.h"
|
||||
#include "Emulator/Profiler.h"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
void* RenderTextureObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("RenderTextureObject::Create");
|
||||
|
||||
EXIT_IF(vaddr_num != 1 || size == nullptr || vaddr == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
auto pixel_format = params[PARAM_FORMAT];
|
||||
auto width = params[PARAM_WIDTH];
|
||||
auto height = params[PARAM_HEIGHT];
|
||||
|
||||
VkFormat vk_format = VK_FORMAT_UNDEFINED;
|
||||
|
||||
switch (pixel_format) // NOLINT
|
||||
{
|
||||
case static_cast<uint64_t>(RenderTextureFormat::R8G8B8A8Unorm): vk_format = VK_FORMAT_R8G8B8A8_UNORM; break;
|
||||
default: EXIT("unknown format: %" PRIu64 "\n", pixel_format);
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(width == 0);
|
||||
EXIT_NOT_IMPLEMENTED(height == 0);
|
||||
|
||||
auto* vk_obj = new RenderTextureVulkanImage;
|
||||
|
||||
vk_obj->extent.width = width;
|
||||
vk_obj->extent.height = height;
|
||||
vk_obj->format = vk_format;
|
||||
vk_obj->image = nullptr;
|
||||
vk_obj->image_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_IMAGE_LAYOUT_UNDEFINED;
|
||||
image_info.usage = static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) |
|
||||
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_SRC_BIT) |
|
||||
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_DST_BIT) |
|
||||
static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
vkCreateImage(ctx->device, &image_info, nullptr, &vk_obj->image);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(vk_obj->image == nullptr);
|
||||
|
||||
vkGetImageMemoryRequirements(ctx->device, vk_obj->image, &mem->requirements);
|
||||
|
||||
mem->property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||
|
||||
bool allocated = VulkanAllocate(ctx, mem);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(!allocated);
|
||||
|
||||
VulkanBindImageMemory(ctx, vk_obj, mem);
|
||||
|
||||
vk_obj->memory = *mem;
|
||||
|
||||
printf("RenderTextureObject::Create()\n");
|
||||
printf("\t mem->requirements.size = %" PRIu64 "\n", mem->requirements.size);
|
||||
printf("\t width = %" PRIu64 "\n", width);
|
||||
printf("\t height = %" PRIu64 "\n", height);
|
||||
printf("\t size = %" PRIu64 "\n", *size);
|
||||
|
||||
// EXIT_NOT_IMPLEMENTED(mem->requirements.size > *size);
|
||||
|
||||
GetUpdateFunc()(ctx, params, vk_obj, vaddr, size, vaddr_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->device, &create_info, nullptr, &vk_obj->image_view);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
|
||||
|
||||
return vk_obj;
|
||||
}
|
||||
|
||||
static bool buffer_is_tiled(uint64_t vaddr, uint64_t size)
|
||||
{
|
||||
if ((size & 0x7u) == 0)
|
||||
{
|
||||
const auto* ptr = reinterpret_cast<const uint64_t*>(vaddr);
|
||||
const auto* ptr_end = reinterpret_cast<const uint64_t*>(vaddr + size / 8);
|
||||
for (uint64_t element = *ptr; ptr < ptr_end; ptr++)
|
||||
{
|
||||
if (element != *ptr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void update_func(GraphicContext* ctx, const uint64_t* params, void* obj, const uint64_t* vaddr, const uint64_t* size, int vaddr_num)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("RenderTextureObject::update_func");
|
||||
|
||||
EXIT_IF(obj == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(params == nullptr);
|
||||
EXIT_IF(vaddr == nullptr || size == nullptr || vaddr_num != 1);
|
||||
|
||||
auto* vk_obj = static_cast<RenderTextureVulkanImage*>(obj);
|
||||
|
||||
bool tiled = (params[RenderTextureObject::PARAM_TILED] != 0);
|
||||
// bool neo = (params[RenderTextureObject::PARAM_NEO] != 0);
|
||||
auto pitch = params[RenderTextureObject::PARAM_PITCH];
|
||||
auto width = params[RenderTextureObject::PARAM_WIDTH];
|
||||
// auto height = params[RenderTextureObject::PARAM_HEIGHT];
|
||||
|
||||
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
if (tiled && buffer_is_tiled(*vaddr, *size))
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(width != pitch);
|
||||
auto* temp_buf = new uint8_t[*size];
|
||||
KYTY_NOT_IMPLEMENTED;
|
||||
// TODO()
|
||||
// TileConvertTiledToLinear(temp_buf, reinterpret_cast<void*>(*vaddr), TileMode::VideoOutTiled, width, height, neo);
|
||||
// UtilFillImage(ctx, vk_obj, temp_buf, *size, pitch);
|
||||
delete[] temp_buf;
|
||||
} else
|
||||
{
|
||||
UtilFillImage(ctx, vk_obj, reinterpret_cast<void*>(*vaddr), *size, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderTextureObject::Equal(const uint64_t* other) const
|
||||
{
|
||||
return (params[PARAM_FORMAT] == other[PARAM_FORMAT] && params[PARAM_WIDTH] == other[PARAM_WIDTH] &&
|
||||
params[PARAM_HEIGHT] == other[PARAM_HEIGHT] && params[PARAM_TILED] == other[PARAM_TILED] &&
|
||||
params[PARAM_PITCH] == other[PARAM_PITCH] && params[PARAM_PITCH] == other[PARAM_PITCH]);
|
||||
}
|
||||
|
||||
static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("RenderTextureObject::delete_func");
|
||||
|
||||
auto* vk_obj = reinterpret_cast<RenderTextureVulkanImage*>(obj);
|
||||
|
||||
EXIT_IF(vk_obj == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
DeleteDescriptor(vk_obj);
|
||||
|
||||
DeleteFramebuffer(vk_obj);
|
||||
|
||||
vkDestroyImageView(ctx->device, vk_obj->image_view, nullptr);
|
||||
|
||||
vkDestroyImage(ctx->device, vk_obj->image, nullptr);
|
||||
|
||||
VulkanFree(ctx, mem);
|
||||
|
||||
delete vk_obj;
|
||||
}
|
||||
|
||||
GpuObject::delete_func_t RenderTextureObject::GetDeleteFunc() const
|
||||
{
|
||||
return delete_func;
|
||||
}
|
||||
|
||||
GpuObject::update_func_t RenderTextureObject::GetUpdateFunc() const
|
||||
{
|
||||
return update_func;
|
||||
}
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#include "Emulator/Graphics/StorageBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/StorageBuffer.h"
|
||||
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
|
||||
+7
-4
@@ -1,4 +1,4 @@
|
||||
#include "Emulator/Graphics/Texture.h"
|
||||
#include "Emulator/Graphics/Objects/Texture.h"
|
||||
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
#include "Kyty/Core/Vector.h"
|
||||
@@ -176,6 +176,7 @@ void* TextureObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const ui
|
||||
vk_obj->format = image_info.format;
|
||||
vk_obj->image = nullptr;
|
||||
vk_obj->image_view = nullptr;
|
||||
vk_obj->layout = image_info.initialLayout;
|
||||
|
||||
vkCreateImage(ctx->device, &image_info, nullptr, &vk_obj->image);
|
||||
|
||||
@@ -227,7 +228,7 @@ static void update_func(GraphicContext* ctx, const uint64_t* params, void* obj,
|
||||
|
||||
auto* vk_obj = static_cast<TextureVulkanImage*>(obj);
|
||||
|
||||
bool tile = (params[TextureObject::PARAM_TILE] != 0);
|
||||
auto tile = params[TextureObject::PARAM_TILE];
|
||||
auto dfmt = params[TextureObject::PARAM_DFMT_NFMT] >> 32u;
|
||||
auto nfmt = params[TextureObject::PARAM_DFMT_NFMT] & 0xffffffffu;
|
||||
auto width = params[TextureObject::PARAM_WIDTH_HEIGHT] >> 32u;
|
||||
@@ -248,6 +249,8 @@ static void update_func(GraphicContext* ctx, const uint64_t* params, void* obj,
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(levels >= 16);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(tile != 8 && tile != 13);
|
||||
|
||||
uint32_t level_sizes[16];
|
||||
|
||||
TileGetTextureSize(dfmt, nfmt, width, height, pitch, levels, tile, neo, nullptr, level_sizes, nullptr, nullptr);
|
||||
@@ -285,14 +288,14 @@ static void update_func(GraphicContext* ctx, const uint64_t* params, void* obj,
|
||||
}
|
||||
}
|
||||
|
||||
if (tile)
|
||||
if (tile == 13)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(pitch != width);
|
||||
auto* temp_buf = new uint8_t[*size];
|
||||
TileConvertTiledToLinear(temp_buf, reinterpret_cast<void*>(*vaddr), TileMode::TextureTiled, dfmt, nfmt, width, height, levels, neo);
|
||||
UtilFillImage(ctx, vk_obj, temp_buf, *size, regions, static_cast<uint64_t>(vk_layout));
|
||||
delete[] temp_buf;
|
||||
} else
|
||||
} else if (tile == 8)
|
||||
{
|
||||
UtilFillImage(ctx, vk_obj, reinterpret_cast<void*>(*vaddr), *size, regions, static_cast<uint64_t>(vk_layout));
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#include "Emulator/Graphics/VertexBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/VertexBuffer.h"
|
||||
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
|
||||
+6
-3
@@ -1,4 +1,4 @@
|
||||
#include "Emulator/Graphics/VideoOutBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/VideoOutBuffer.h"
|
||||
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
|
||||
@@ -37,6 +37,7 @@ void* VideoOutBufferObject::Create(GraphicContext* ctx, const uint64_t* vaddr, c
|
||||
vk_obj->format = VK_FORMAT_B8G8R8A8_SRGB;
|
||||
vk_obj->image = nullptr;
|
||||
vk_obj->image_view = nullptr;
|
||||
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
VkImageCreateInfo image_info {};
|
||||
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
@@ -50,7 +51,7 @@ void* VideoOutBufferObject::Create(GraphicContext* ctx, const uint64_t* vaddr, c
|
||||
image_info.arrayLayers = 1;
|
||||
image_info.format = vk_obj->format;
|
||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
image_info.initialLayout = vk_obj->layout;
|
||||
image_info.usage = static_cast<VkImageUsageFlags>(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;
|
||||
@@ -141,6 +142,8 @@ static void update_func(GraphicContext* ctx, const uint64_t* params, void* obj,
|
||||
auto width = params[VideoOutBufferObject::PARAM_WIDTH];
|
||||
auto height = params[VideoOutBufferObject::PARAM_HEIGHT];
|
||||
|
||||
vk_obj->layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
if (tiled && buffer_is_tiled(*vaddr, *size))
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(width != pitch);
|
||||
@@ -158,7 +161,7 @@ bool VideoOutBufferObject::Equal(const uint64_t* other) const
|
||||
{
|
||||
return (params[PARAM_FORMAT] == other[PARAM_FORMAT] && params[PARAM_WIDTH] == other[PARAM_WIDTH] &&
|
||||
params[PARAM_HEIGHT] == other[PARAM_HEIGHT] && params[PARAM_TILED] == other[PARAM_TILED] &&
|
||||
params[PARAM_PITCH] == other[PARAM_PITCH]);
|
||||
params[PARAM_PITCH] == other[PARAM_PITCH] && params[PARAM_NEO] == other[PARAM_NEO]);
|
||||
}
|
||||
|
||||
static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
|
||||
@@ -3012,7 +3012,7 @@ ShaderCode ShaderParsePS(const PixelShaderInfo* regs)
|
||||
ps_print("ShaderParsePS()", regs->ps_regs);
|
||||
ps_check(regs->ps_regs);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(regs->ps_regs.user_sgpr != regs->ps_user_sgpr.count);
|
||||
EXIT_NOT_IMPLEMENTED(regs->ps_regs.user_sgpr > regs->ps_user_sgpr.count);
|
||||
|
||||
const auto* header = GetBinaryInfo(src);
|
||||
|
||||
|
||||
@@ -423,7 +423,7 @@ void TileConvertTiledToLinear(void* dst, const void* src, TileMode mode, uint32_
|
||||
uint32_t padded_height[16] = {0};
|
||||
uint32_t level_sizes[16] = {0};
|
||||
|
||||
TileGetTextureSize(dfmt, nfmt, width, height, width, levels, true, neo, nullptr, level_sizes, padded_width, padded_height);
|
||||
TileGetTextureSize(dfmt, nfmt, width, height, width, levels, 13, neo, nullptr, level_sizes, padded_width, padded_height);
|
||||
|
||||
uint32_t mip_width = width;
|
||||
uint32_t mip_height = height;
|
||||
@@ -611,8 +611,8 @@ void TileGetVideoOutSize(uint32_t width, uint32_t height, bool tile, bool neo, u
|
||||
*pitch = ret_pitch;
|
||||
}
|
||||
|
||||
void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t pitch, uint32_t levels, bool tile, bool neo,
|
||||
uint32_t* total_size, uint32_t* level_sizes, uint32_t* padded_width, uint32_t* padded_height)
|
||||
void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t height, uint32_t pitch, uint32_t levels, uint32_t tile,
|
||||
bool neo, uint32_t* total_size, uint32_t* level_sizes, uint32_t* padded_width, uint32_t* padded_height)
|
||||
{
|
||||
struct Padded
|
||||
{
|
||||
@@ -627,7 +627,7 @@ void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t h
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t levels;
|
||||
bool tile;
|
||||
uint32_t tile;
|
||||
bool neo;
|
||||
uint32_t size[16];
|
||||
Padded padded[16];
|
||||
@@ -635,22 +635,28 @@ void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t h
|
||||
|
||||
static const TextureInfo infos[] = {
|
||||
// clang-format off
|
||||
{ 10, 9, 512, 512, 10, false, false, {1048576, 262144, 65536, 16384, 4096, 1024, 512, 256, 256, 256, },
|
||||
|
||||
{ 10, 9, 512, 512, 10, 8, false, {1048576, 262144, 65536, 16384, 4096, 1024, 512, 256, 256, 256, },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
|
||||
{ 10, 9, 512, 512, 10, false, true, {1048576, 262144, 65536, 16384, 4096, 1024, 512, 256, 256, 256, },
|
||||
{ 10, 9, 512, 512, 10, 8, true, {1048576, 262144, 65536, 16384, 4096, 1024, 512, 256, 256, 256, },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
|
||||
{ 10, 9, 512, 512, 10, true, false, {1048576, 262144, 65536, 16384, 4096, 1024, 256, 256, 256, 256, },
|
||||
{ 10, 9, 512, 512, 10, 13, false, {1048576, 262144, 65536, 16384, 4096, 1024, 256, 256, 256, 256, },
|
||||
{ {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
|
||||
{ 10, 9, 512, 512, 10, true, true, {1048576, 262144, 65536, 16384, 4096, 1024, 256, 256, 256, 256, },
|
||||
{ 10, 9, 512, 512, 10, 13, true, {1048576, 262144, 65536, 16384, 4096, 1024, 256, 256, 256, 256, },
|
||||
{ {512, 512}, {256, 256}, {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
|
||||
{ 37, 9, 512, 512, 10, false, false, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
|
||||
{ 37, 9, 512, 512, 10, 8, false, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
|
||||
{ 37, 9, 512, 512, 10, false, true, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
|
||||
{ 37, 9, 512, 512, 10, 8, true, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
|
||||
{ 37, 9, 512, 512, 10, true, false, {262144, 65536, 16384, 4096, 1024, 1024, 1024, 1024, 1024, 1024, },
|
||||
{ 37, 9, 512, 512, 10, 13, false, {262144, 65536, 16384, 4096, 1024, 1024, 1024, 1024, 1024, 1024, },
|
||||
{ {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
|
||||
{ 37, 9, 512, 512, 10, true, true, {262144, 65536, 16384, 4096, 1024, 1024, 1024, 1024, 1024, 1024, },
|
||||
{ 37, 9, 512, 512, 10, 13, true, {262144, 65536, 16384, 4096, 1024, 1024, 1024, 1024, 1024, 1024, },
|
||||
{ {128, 128}, {64, 64}, {32, 32}, {16, 16}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8}, } },
|
||||
|
||||
{ 10, 0, 256, 256, 9, 14, false, {262144, 65536, 16384, 4096, 1024, 256, 256, 256, 256, },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
|
||||
{ 10, 0, 256, 256, 9, 14, true, {262144, 65536, 16384, 4096, 1024, 256, 256, 256, 256, },
|
||||
{ {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } },
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
@@ -684,7 +690,7 @@ void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t h
|
||||
}
|
||||
}
|
||||
|
||||
if (!tile && levels == 1 && dfmt == 10 && nfmt == 9)
|
||||
if (tile == 8 && levels == 1 && dfmt == 10 && nfmt == 9)
|
||||
{
|
||||
uint32_t size = pitch * height * 4;
|
||||
if (total_size != nullptr)
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
#include "Kyty/Core/Vector.h"
|
||||
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/GraphicContext.h"
|
||||
#include "Emulator/Graphics/GraphicsRender.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
#include "Emulator/Profiler.h"
|
||||
|
||||
#include "vulkan/vulkan_core.h"
|
||||
@@ -14,11 +14,13 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
static void set_image_layout(VkCommandBuffer buffer, VkImage image, uint32_t levels, VkImageAspectFlags aspect_mask,
|
||||
static void set_image_layout(VkCommandBuffer buffer, VulkanImage* dst_image, uint32_t levels, VkImageAspectFlags aspect_mask,
|
||||
VkImageLayout old_image_layout, VkImageLayout new_image_layout)
|
||||
{
|
||||
EXIT_IF(buffer == nullptr);
|
||||
|
||||
EXIT_IF(dst_image->layout != old_image_layout);
|
||||
|
||||
VkImageMemoryBarrier image_memory_barrier {};
|
||||
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
image_memory_barrier.pNext = nullptr;
|
||||
@@ -28,7 +30,7 @@ static void set_image_layout(VkCommandBuffer buffer, VkImage image, uint32_t lev
|
||||
image_memory_barrier.newLayout = new_image_layout;
|
||||
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.image = image;
|
||||
image_memory_barrier.image = dst_image->image;
|
||||
image_memory_barrier.subresourceRange.aspectMask = aspect_mask;
|
||||
image_memory_barrier.subresourceRange.baseMipLevel = 0;
|
||||
image_memory_barrier.subresourceRange.levelCount = levels;
|
||||
@@ -80,9 +82,11 @@ static void set_image_layout(VkCommandBuffer buffer, VkImage image, uint32_t lev
|
||||
VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
|
||||
vkCmdPipelineBarrier(buffer, src_stages, dest_stages, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
|
||||
|
||||
dst_image->layout = new_image_layout;
|
||||
}
|
||||
|
||||
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, uint32_t src_pitch, VideoOutVulkanImage* dst_image)
|
||||
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, uint32_t src_pitch, VulkanImage* dst_image)
|
||||
{
|
||||
EXIT_IF(src_buffer == nullptr);
|
||||
EXIT_IF(src_buffer->buffer == nullptr);
|
||||
@@ -91,8 +95,7 @@ void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, uint32_t
|
||||
|
||||
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
|
||||
|
||||
set_image_layout(vk_buffer, dst_image->image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
set_image_layout(vk_buffer, dst_image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
VkBufferImageCopy region {};
|
||||
region.bufferOffset = 0;
|
||||
@@ -109,7 +112,7 @@ void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, uint32_t
|
||||
|
||||
vkCmdCopyBufferToImage(vk_buffer, src_buffer->buffer, dst_image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
set_image_layout(vk_buffer, dst_image->image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
set_image_layout(vk_buffer, dst_image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
@@ -142,16 +145,16 @@ void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, TextureV
|
||||
index++;
|
||||
}
|
||||
|
||||
set_image_layout(vk_buffer, dst_image->image, index, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
set_image_layout(vk_buffer, dst_image, index, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
vkCmdCopyBufferToImage(vk_buffer, src_buffer->buffer, dst_image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, index, region);
|
||||
|
||||
set_image_layout(vk_buffer, dst_image->image, index, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
set_image_layout(vk_buffer, dst_image, index, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
/*VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL*/ static_cast<VkImageLayout>(dst_layout));
|
||||
}
|
||||
|
||||
void UtilBlitImage(CommandBuffer* buffer, VideoOutVulkanImage* src_image, VulkanSwapchain* dst_swapchain)
|
||||
void UtilBlitImage(CommandBuffer* buffer, VulkanImage* src_image, VulkanSwapchain* dst_swapchain)
|
||||
{
|
||||
EXIT_IF(src_image == nullptr);
|
||||
EXIT_IF(src_image->image == nullptr);
|
||||
@@ -159,11 +162,14 @@ void UtilBlitImage(CommandBuffer* buffer, VideoOutVulkanImage* src_image, Vulkan
|
||||
|
||||
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
|
||||
|
||||
auto* blt_dst_image = dst_swapchain->swapchain_images[dst_swapchain->current_index];
|
||||
VulkanImage swapchain_image {};
|
||||
|
||||
set_image_layout(vk_buffer, src_image->image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
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, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
set_image_layout(vk_buffer, blt_dst_image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
set_image_layout(vk_buffer, &swapchain_image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
VkImageBlit region {};
|
||||
@@ -188,10 +194,10 @@ void UtilBlitImage(CommandBuffer* buffer, VideoOutVulkanImage* src_image, Vulkan
|
||||
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, blt_dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ®ion, VK_FILTER_LINEAR);
|
||||
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->image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
set_image_layout(vk_buffer, src_image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
@@ -231,7 +237,7 @@ void VulkanDeleteBuffer(GraphicContext* gctx, VulkanBuffer* buffer)
|
||||
buffer->buffer = nullptr;
|
||||
}
|
||||
|
||||
void UtilFillImage(GraphicContext* ctx, VideoOutVulkanImage* image, const void* src_data, uint64_t size, uint32_t src_pitch)
|
||||
void UtilFillImage(GraphicContext* ctx, VulkanImage* image, const void* src_data, uint64_t size, uint32_t src_pitch)
|
||||
{
|
||||
KYTY_PROFILER_FUNCTION();
|
||||
|
||||
@@ -262,7 +268,7 @@ void UtilFillImage(GraphicContext* ctx, VideoOutVulkanImage* image, const void*
|
||||
VulkanDeleteBuffer(ctx, &staging_buffer);
|
||||
}
|
||||
|
||||
void UtilSetImageLayoutOptimal(DepthStencilVulkanImage* image)
|
||||
void UtilSetDepthLayoutOptimal(DepthStencilVulkanImage* image)
|
||||
{
|
||||
CommandBuffer buffer;
|
||||
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
|
||||
@@ -280,14 +286,14 @@ void UtilSetImageLayoutOptimal(DepthStencilVulkanImage* image)
|
||||
aspect_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
|
||||
set_image_layout(vk_buffer, image->image, 1, aspect_mask, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
set_image_layout(vk_buffer, image, 1, aspect_mask, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
buffer.End();
|
||||
buffer.Execute();
|
||||
buffer.WaitForFence();
|
||||
}
|
||||
|
||||
void UtilSetImageLayoutOptimal(VideoOutVulkanImage* image)
|
||||
void UtilSetImageLayoutOptimal(VulkanImage* image)
|
||||
{
|
||||
CommandBuffer buffer;
|
||||
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
|
||||
@@ -300,7 +306,7 @@ void UtilSetImageLayoutOptimal(VideoOutVulkanImage* image)
|
||||
|
||||
VkImageAspectFlags aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
set_image_layout(vk_buffer, image->image, 1, aspect_mask, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
set_image_layout(vk_buffer, image, 1, aspect_mask, image->layout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
buffer.End();
|
||||
buffer.Execute();
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Config.h"
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/GraphicsRender.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Objects/VideoOutBuffer.h"
|
||||
#include "Emulator/Graphics/Tile.h"
|
||||
#include "Emulator/Graphics/VideoOutBuffer.h"
|
||||
#include "Emulator/Graphics/Window.h"
|
||||
#include "Emulator/Kernel/Pthread.h"
|
||||
#include "Emulator/Libs/Errno.h"
|
||||
@@ -845,7 +845,7 @@ KYTY_SYSV_ABI int VideoOutRegisterBuffers(int handle, int start_index, void* con
|
||||
ctx->buffers[i + start_index].buffer = addresses[i];
|
||||
ctx->buffers[i + start_index].buffer_size = buffer_size;
|
||||
ctx->buffers[i + start_index].buffer_pitch = buffer_pitch;
|
||||
ctx->buffers[i + start_index].buffer_vulkan = static_cast<Graphics::VideoOutVulkanImage*>(Graphics::GpuMemoryGetObject(
|
||||
ctx->buffers[i + start_index].buffer_vulkan = static_cast<Graphics::VideoOutVulkanImage*>(Graphics::GpuMemoryCreateObject(
|
||||
g_video_out_context->GetGraphicCtx(), reinterpret_cast<uint64_t>(addresses[i]), buffer_size, vulkan_buffer_info));
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(ctx->buffers[i + start_index].buffer_vulkan == nullptr);
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include "Kyty/Core/Threads.h"
|
||||
#include "Kyty/Core/Vector.h"
|
||||
|
||||
#include "Emulator/Graphics/GpuMemory.h"
|
||||
#include "Emulator/Graphics/GraphicsRun.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
#include "Emulator/Graphics/Window.h"
|
||||
#include "Emulator/Libs/Errno.h"
|
||||
#include "Emulator/Libs/Libs.h"
|
||||
|
||||
@@ -27,8 +27,8 @@ public:
|
||||
InvalCount
|
||||
};
|
||||
|
||||
KernelSemaPrivate(const String& name, bool fifo, int init_count, int max_count)
|
||||
: m_name(name), m_fifo_order(fifo), m_count(init_count), m_init_count(init_count), m_max_count(max_count) {};
|
||||
KernelSemaPrivate(const String& name, bool /*fifo*/, int init_count, int max_count)
|
||||
: m_name(name), /*m_fifo_order(fifo),*/ m_count(init_count), m_init_count(init_count), m_max_count(max_count) {};
|
||||
virtual ~KernelSemaPrivate();
|
||||
|
||||
KYTY_CLASS_NO_COPY(KernelSemaPrivate);
|
||||
@@ -53,15 +53,15 @@ private:
|
||||
Deleted
|
||||
};
|
||||
|
||||
Core::Mutex m_mutex;
|
||||
Core::CondVar m_cond_var;
|
||||
String m_name;
|
||||
Status m_status = Status::Set;
|
||||
Vector<int> m_waiting_threads;
|
||||
[[maybe_unused]] bool m_fifo_order;
|
||||
int m_count;
|
||||
int m_init_count;
|
||||
int m_max_count;
|
||||
Core::Mutex m_mutex;
|
||||
Core::CondVar m_cond_var;
|
||||
String m_name;
|
||||
Status m_status = Status::Set;
|
||||
Vector<int> m_waiting_threads;
|
||||
// bool m_fifo_order;
|
||||
int m_count;
|
||||
int m_init_count;
|
||||
int m_max_count;
|
||||
};
|
||||
|
||||
KernelSemaPrivate::~KernelSemaPrivate()
|
||||
|
||||
Reference in New Issue
Block a user