mirror of
https://github.com/InoriRus/Kyty.git
synced 2026-08-27 20:56:41 +00:00
render to mips
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
version: 0.0.9.build-{build}
|
||||
version: 0.0.10.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.9)
|
||||
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.10)
|
||||
|
||||
include(src_script.cmake)
|
||||
|
||||
|
||||
@@ -87,6 +87,10 @@ struct TextureVulkanImage: public VulkanImage
|
||||
{
|
||||
};
|
||||
|
||||
struct StorageTextureVulkanImage: public VulkanImage
|
||||
{
|
||||
};
|
||||
|
||||
struct RenderTextureVulkanImage: public VulkanImage
|
||||
{
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ class CommandProcessor;
|
||||
struct VideoOutVulkanImage;
|
||||
struct DepthStencilVulkanImage;
|
||||
struct TextureVulkanImage;
|
||||
struct StorageTextureVulkanImage;
|
||||
struct RenderTextureVulkanImage;
|
||||
struct VulkanCommandPool;
|
||||
struct VulkanBuffer;
|
||||
@@ -90,6 +91,7 @@ void DeleteFramebuffer(DepthStencilVulkanImage* image);
|
||||
void DeleteFramebuffer(RenderTextureVulkanImage* image);
|
||||
void DeleteDescriptor(VulkanBuffer* buffer);
|
||||
void DeleteDescriptor(TextureVulkanImage* image);
|
||||
void DeleteDescriptor(StorageTextureVulkanImage* image);
|
||||
void DeleteDescriptor(RenderTextureVulkanImage* image);
|
||||
|
||||
int GraphicsRenderAddEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id, void* udata);
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class DepthStencilBufferObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
@@ -33,12 +30,13 @@ public:
|
||||
type = Graphics::GpuMemoryObjectType::DepthStencilBuffer;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
[[nodiscard]] create_func_t GetCreateFunc() const override;
|
||||
[[nodiscard]] create_from_objects_func_t GetCreateFromObjectsFunc() const override { return nullptr; };
|
||||
[[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
|
||||
|
||||
@@ -34,6 +34,7 @@ enum class GpuMemoryObjectType : uint64_t
|
||||
StorageBuffer,
|
||||
Texture,
|
||||
RenderTexture,
|
||||
StorageTexture,
|
||||
|
||||
Max
|
||||
};
|
||||
@@ -47,10 +48,14 @@ struct GpuMemoryObject
|
||||
class GpuObject
|
||||
{
|
||||
public:
|
||||
using write_back_func_t = void (*)(GraphicContext* ctx, void* obj, const uint64_t* vaddr, const uint64_t* size, int vaddr_num);
|
||||
using delete_func_t = void (*)(GraphicContext* ctx, void* obj, VulkanMemory* mem);
|
||||
using update_func_t = void (*)(GraphicContext* ctx, const uint64_t* params, void* obj, const uint64_t* vaddr, const uint64_t* size,
|
||||
int vaddr_num);
|
||||
using create_func_t = void* (*)(GraphicContext* ctx, const uint64_t* params, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem);
|
||||
using create_from_objects_func_t = void* (*)(GraphicContext* ctx, const uint64_t* params, const Vector<GpuMemoryObject>& objects,
|
||||
VulkanMemory* mem);
|
||||
using write_back_func_t = void (*)(GraphicContext* ctx, void* obj, const uint64_t* vaddr, const uint64_t* size, int vaddr_num);
|
||||
using delete_func_t = void (*)(GraphicContext* ctx, void* obj, VulkanMemory* mem);
|
||||
using update_func_t = void (*)(GraphicContext* ctx, const uint64_t* params, void* obj, const uint64_t* vaddr, const uint64_t* size,
|
||||
int vaddr_num);
|
||||
|
||||
static constexpr int PARAMS_MAX = 8;
|
||||
|
||||
@@ -59,12 +64,13 @@ public:
|
||||
|
||||
KYTY_CLASS_DEFAULT_COPY(GpuObject);
|
||||
|
||||
virtual void* Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const = 0;
|
||||
virtual bool Equal(const uint64_t* other) const = 0;
|
||||
virtual bool Equal(const uint64_t* other) const = 0;
|
||||
|
||||
[[nodiscard]] virtual write_back_func_t GetWriteBackFunc() const = 0;
|
||||
[[nodiscard]] virtual delete_func_t GetDeleteFunc() const = 0;
|
||||
[[nodiscard]] virtual update_func_t GetUpdateFunc() const = 0;
|
||||
[[nodiscard]] virtual create_func_t GetCreateFunc() const = 0;
|
||||
[[nodiscard]] virtual create_from_objects_func_t GetCreateFromObjectsFunc() const = 0;
|
||||
[[nodiscard]] virtual write_back_func_t GetWriteBackFunc() const = 0;
|
||||
[[nodiscard]] virtual delete_func_t GetDeleteFunc() const = 0;
|
||||
[[nodiscard]] virtual update_func_t GetUpdateFunc() const = 0;
|
||||
|
||||
uint64_t params[PARAMS_MAX] = {};
|
||||
bool check_hash = false;
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class IndexBufferGpuObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
@@ -22,12 +19,13 @@ public:
|
||||
type = Graphics::GpuMemoryObjectType::IndexBuffer;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
[[nodiscard]] create_func_t GetCreateFunc() const override;
|
||||
[[nodiscard]] create_from_objects_func_t GetCreateFromObjectsFunc() const override { return nullptr; };
|
||||
[[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
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct Label;
|
||||
struct GraphicContext;
|
||||
class CommandBuffer;
|
||||
struct VulkanMemory;
|
||||
|
||||
void LabelInit();
|
||||
|
||||
@@ -46,12 +44,13 @@ public:
|
||||
type = Graphics::GpuMemoryObjectType::Label;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
[[nodiscard]] create_func_t GetCreateFunc() const override;
|
||||
[[nodiscard]] create_from_objects_func_t GetCreateFromObjectsFunc() const override { return nullptr; };
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override { return nullptr; };
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
};
|
||||
|
||||
void LabelSet(CommandBuffer* buffer, Label* label);
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
enum class RenderTextureFormat : uint64_t
|
||||
{
|
||||
R8G8B8A8Unorm
|
||||
@@ -40,12 +37,13 @@ public:
|
||||
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;
|
||||
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;
|
||||
[[nodiscard]] create_func_t GetCreateFunc() const override;
|
||||
[[nodiscard]] create_from_objects_func_t GetCreateFromObjectsFunc() const override { return nullptr; };
|
||||
[[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
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class StorageBufferGpuObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
@@ -25,12 +22,13 @@ public:
|
||||
type = Graphics::GpuMemoryObjectType::StorageBuffer;
|
||||
}
|
||||
|
||||
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;
|
||||
bool Equal(const uint64_t* other) const override;
|
||||
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override;
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
[[nodiscard]] create_func_t GetCreateFunc() const override;
|
||||
[[nodiscard]] create_from_objects_func_t GetCreateFromObjectsFunc() const override { return nullptr; };
|
||||
[[nodiscard]] write_back_func_t GetWriteBackFunc() const override;
|
||||
[[nodiscard]] delete_func_t GetDeleteFunc() const override;
|
||||
[[nodiscard]] update_func_t GetUpdateFunc() const override;
|
||||
};
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_STORAGETEXTURE_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_STORAGETEXTURE_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Graphics/Objects/GpuMemory.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
class StorageTextureObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
static constexpr int PARAM_DFMT_NFMT = 0;
|
||||
static constexpr int PARAM_PITCH = 1;
|
||||
static constexpr int PARAM_WIDTH_HEIGHT = 2;
|
||||
static constexpr int PARAM_LEVELS = 3;
|
||||
static constexpr int PARAM_TILE = 4;
|
||||
static constexpr int PARAM_NEO = 5;
|
||||
static constexpr int PARAM_SWIZZLE = 6;
|
||||
|
||||
StorageTextureObject(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)
|
||||
{
|
||||
params[PARAM_DFMT_NFMT] = (static_cast<uint64_t>(dfmt) << 32u) | nfmt;
|
||||
params[PARAM_PITCH] = pitch;
|
||||
params[PARAM_WIDTH_HEIGHT] = (static_cast<uint64_t>(width) << 32u) | height;
|
||||
params[PARAM_LEVELS] = levels;
|
||||
params[PARAM_TILE] = tile;
|
||||
params[PARAM_NEO] = neo ? 1 : 0;
|
||||
params[PARAM_SWIZZLE] = swizzle;
|
||||
check_hash = true;
|
||||
type = Graphics::GpuMemoryObjectType::StorageTexture;
|
||||
}
|
||||
|
||||
bool Equal(const uint64_t* other) const override;
|
||||
|
||||
[[nodiscard]] create_func_t GetCreateFunc() const override;
|
||||
[[nodiscard]] create_from_objects_func_t GetCreateFromObjectsFunc() const override { return nullptr; };
|
||||
[[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_STORAGETEXTURE_H_ */
|
||||
@@ -10,31 +10,23 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class TextureObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
static constexpr int TEXTURE_USAGE_SAMPLED = 0;
|
||||
static constexpr int TEXTURE_USAGE_STORAGE = 1;
|
||||
|
||||
static constexpr int PARAM_DFMT_NFMT = 0;
|
||||
static constexpr int PARAM_PITCH = 1;
|
||||
static constexpr int PARAM_WIDTH_HEIGHT = 2;
|
||||
static constexpr int PARAM_USAGE = 3;
|
||||
static constexpr int PARAM_LEVELS = 4;
|
||||
static constexpr int PARAM_TILE = 5;
|
||||
static constexpr int PARAM_NEO = 6;
|
||||
static constexpr int PARAM_SWIZZLE = 7;
|
||||
static constexpr int PARAM_LEVELS = 3;
|
||||
static constexpr int PARAM_TILE = 4;
|
||||
static constexpr int PARAM_NEO = 5;
|
||||
static constexpr int PARAM_SWIZZLE = 6;
|
||||
|
||||
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)
|
||||
uint32_t swizzle)
|
||||
{
|
||||
params[PARAM_DFMT_NFMT] = (static_cast<uint64_t>(dfmt) << 32u) | nfmt;
|
||||
params[PARAM_PITCH] = pitch;
|
||||
params[PARAM_WIDTH_HEIGHT] = (static_cast<uint64_t>(width) << 32u) | height;
|
||||
params[PARAM_USAGE] = usage;
|
||||
params[PARAM_LEVELS] = levels;
|
||||
params[PARAM_TILE] = tile;
|
||||
params[PARAM_NEO] = neo ? 1 : 0;
|
||||
@@ -43,12 +35,13 @@ public:
|
||||
type = Graphics::GpuMemoryObjectType::Texture;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
[[nodiscard]] create_func_t GetCreateFunc() const override;
|
||||
[[nodiscard]] create_from_objects_func_t GetCreateFromObjectsFunc() 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
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class VertexBufferGpuObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
@@ -22,12 +19,13 @@ public:
|
||||
type = Graphics::GpuMemoryObjectType::VertexBuffer;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
[[nodiscard]] create_func_t GetCreateFunc() const override;
|
||||
[[nodiscard]] create_from_objects_func_t GetCreateFromObjectsFunc() const override { return nullptr; };
|
||||
[[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
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanMemory;
|
||||
|
||||
class VideoOutBufferObject: public GpuObject
|
||||
{
|
||||
public:
|
||||
@@ -35,12 +32,13 @@ public:
|
||||
type = Graphics::GpuMemoryObjectType::VideoOutBuffer;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
[[nodiscard]] create_func_t GetCreateFunc() const override;
|
||||
[[nodiscard]] create_from_objects_func_t GetCreateFromObjectsFunc() const override { return nullptr; };
|
||||
[[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
|
||||
|
||||
@@ -42,6 +42,7 @@ enum class ShaderInstructionType
|
||||
Exp,
|
||||
ImageLoad,
|
||||
ImageSample,
|
||||
ImageStoreMip,
|
||||
SAddcU32,
|
||||
SAddI32,
|
||||
SAddU32,
|
||||
@@ -284,6 +285,7 @@ enum Format : uint64_t
|
||||
Vdata3Vaddr3StSsDmask7 = FormatDefine({DA3, S0A3, S1A8, S2A4, Dmask7}),
|
||||
Vdata4Vaddr3StSsDmaskF = FormatDefine({DA4, S0A3, S1A8, S2A4, DmaskF}),
|
||||
Vdata4Vaddr3StDmaskF = FormatDefine({DA4, S0A3, S1A8, DmaskF}),
|
||||
Vdata4Vaddr4StDmaskF = FormatDefine({DA4, S0A4, S1A8, DmaskF}),
|
||||
VdstVsrc0Vsrc1Smask2 = FormatDefine({D, S0, S1, S2A2}),
|
||||
VdstVsrc0Vsrc1Vsrc2 = FormatDefine({D, S0, S1, S2}),
|
||||
VdstVsrcAttrChan = FormatDefine({D, S0, Attr}),
|
||||
@@ -570,6 +572,13 @@ enum class ShaderStorageUsage
|
||||
ReadWrite,
|
||||
};
|
||||
|
||||
enum class ShaderTextureUsage
|
||||
{
|
||||
Unknown,
|
||||
ReadOnly,
|
||||
ReadWrite,
|
||||
};
|
||||
|
||||
struct ShaderStorageResources
|
||||
{
|
||||
static constexpr int BUFFERS_MAX = 16;
|
||||
@@ -588,11 +597,13 @@ struct ShaderTextureResources
|
||||
static constexpr int RES_MAX = 16;
|
||||
|
||||
ShaderTextureResource textures[RES_MAX];
|
||||
ShaderTextureUsage usages[RES_MAX] = {};
|
||||
int slots[RES_MAX] = {0};
|
||||
int start_register[RES_MAX] = {0};
|
||||
bool extended[RES_MAX] = {};
|
||||
int textures_num = 0;
|
||||
int binding_index = 0;
|
||||
int binding_sampled_index = 0;
|
||||
int binding_storage_index = 0;
|
||||
};
|
||||
|
||||
struct ShaderSamplerResources
|
||||
@@ -641,7 +652,9 @@ struct ShaderBindResources
|
||||
|
||||
struct ShaderBindParameters
|
||||
{
|
||||
bool textures2D_without_sampler = false;
|
||||
bool textures2d_without_sampler[ShaderTextureResources::RES_MAX] = {};
|
||||
int textures2d_sampled_num = 0;
|
||||
int textures2d_storage_num = 0;
|
||||
};
|
||||
|
||||
struct ShaderVertexInputInfo
|
||||
@@ -674,9 +687,12 @@ struct ShaderPixelInputInfo
|
||||
uint8_t target_output_mode[8] = {};
|
||||
bool ps_pos_xy = false;
|
||||
bool ps_pixel_kill_enable = false;
|
||||
bool ps_early_z = false;
|
||||
bool ps_execute_on_noop = false;
|
||||
ShaderBindResources bind;
|
||||
};
|
||||
|
||||
void ShaderCalcBindingIndices(ShaderBindResources* bind);
|
||||
void ShaderGetInputInfoVS(const VertexShaderInfo* regs, ShaderVertexInputInfo* info);
|
||||
void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputInfo* vs_info, ShaderPixelInputInfo* ps_info);
|
||||
void ShaderGetInputInfoCS(const ComputeShaderInfo* regs, ShaderComputeInputInfo* info);
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty {
|
||||
@@ -18,25 +20,42 @@ class CommandBuffer;
|
||||
struct GraphicContext;
|
||||
struct VulkanBuffer;
|
||||
struct VulkanImage;
|
||||
struct TextureVulkanImage;
|
||||
struct DepthStencilVulkanImage;
|
||||
struct VulkanSwapchain;
|
||||
|
||||
struct BufferImageCopy
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t pitch;
|
||||
uint32_t dst_level;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t pitch;
|
||||
int dst_x;
|
||||
int dst_y;
|
||||
};
|
||||
|
||||
struct ImageImageCopy
|
||||
{
|
||||
VulkanImage* src_image;
|
||||
uint32_t src_level;
|
||||
uint32_t dst_level;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
int src_x;
|
||||
int src_y;
|
||||
int dst_x;
|
||||
int dst_y;
|
||||
};
|
||||
|
||||
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 UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, VulkanImage* dst_image, const Vector<BufferImageCopy>& regions,
|
||||
uint64_t dst_layout);
|
||||
void UtilImageToImage(CommandBuffer* buffer, const Vector<ImageImageCopy>& regions, VulkanImage* dst_image, uint64_t dst_layout);
|
||||
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 UtilFillImage(GraphicContext* ctx, VulkanImage* dst_image, const void* src_data, uint64_t size, const Vector<BufferImageCopy>& regions,
|
||||
uint64_t dst_layout);
|
||||
void UtilFillImage(GraphicContext* ctx, const Vector<ImageImageCopy>& regions, VulkanImage* dst_image, uint64_t dst_layout);
|
||||
void UtilCopyBuffer(VulkanBuffer* src_buffer, VulkanBuffer* dst_buffer, uint64_t size);
|
||||
void UtilSetDepthLayoutOptimal(DepthStencilVulkanImage* image);
|
||||
void UtilSetImageLayoutOptimal(VulkanImage* image);
|
||||
@@ -44,6 +63,31 @@ void UtilSetImageLayoutOptimal(VulkanImage* image);
|
||||
void VulkanCreateBuffer(GraphicContext* gctx, uint64_t size, VulkanBuffer* buffer);
|
||||
void VulkanDeleteBuffer(GraphicContext* gctx, VulkanBuffer* buffer);
|
||||
|
||||
inline std::pair<int, int> UtilCalcMipmapOffset(uint32_t lod, uint32_t width, uint32_t height)
|
||||
{
|
||||
uint32_t mip_width = width;
|
||||
uint32_t mip_height = height;
|
||||
int mip_x = 0;
|
||||
int mip_y = 0;
|
||||
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
{
|
||||
if (i == lod)
|
||||
{
|
||||
return {mip_x, mip_y};
|
||||
}
|
||||
|
||||
bool odd = ((i & 1u) != 0);
|
||||
mip_x += static_cast<int>(odd ? mip_width : 0);
|
||||
mip_y += static_cast<int>(odd ? 0 : mip_height);
|
||||
|
||||
mip_width >>= (mip_width > 1 ? 1u : 0u);
|
||||
mip_height >>= (mip_height > 1 ? 1u : 0u);
|
||||
}
|
||||
|
||||
return {mip_x, mip_y};
|
||||
}
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "Emulator/Graphics/Objects/Label.h"
|
||||
#include "Emulator/Graphics/Objects/RenderTexture.h"
|
||||
#include "Emulator/Graphics/Objects/StorageBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/StorageTexture.h"
|
||||
#include "Emulator/Graphics/Objects/Texture.h"
|
||||
#include "Emulator/Graphics/Objects/VertexBuffer.h"
|
||||
#include "Emulator/Graphics/Objects/VideoOutBuffer.h"
|
||||
@@ -161,16 +162,15 @@ public:
|
||||
virtual ~DescriptorCache() { KYTY_NOT_IMPLEMENTED; }
|
||||
KYTY_CLASS_NO_COPY(DescriptorCache);
|
||||
|
||||
VkDescriptorSetLayout GetDescriptorSetLayout(Stage stage, int storage_buffers_num, int textures2d_sampled_num,
|
||||
int textures2d_storage_num, int samplers_num, int gds_buffers_num);
|
||||
VkDescriptorSetLayout GetDescriptorSetLayout(Stage stage, const ShaderBindResources& bind, const ShaderBindParameters& bind_params);
|
||||
|
||||
VulkanDescriptorSet* Allocate(Stage stage, int storage_buffers_num, int textures2d_sampled_num, int textures2d_storage_num,
|
||||
int samplers_num, int gds_buffers_num);
|
||||
void Free(VulkanDescriptorSet* set);
|
||||
|
||||
VulkanDescriptorSet* GetDescriptor(Stage stage, int storage_buffers_num, VulkanBuffer** storage_buffers, 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);
|
||||
VulkanDescriptorSet* GetDescriptor(Stage stage, VulkanBuffer** storage_buffers, VulkanImage** textures2d_sampled,
|
||||
VulkanImage** textures2d_storage, uint64_t* samplers, VulkanBuffer** gds_buffers,
|
||||
const ShaderBindResources& bind, const ShaderBindParameters& bind_params);
|
||||
void FreeDescriptor(VulkanBuffer* buffer);
|
||||
void FreeDescriptor(VulkanImage* image);
|
||||
|
||||
@@ -1603,10 +1603,7 @@ static void CreateLayout(VkDescriptorSetLayout* set_layouts, uint32_t* set_layou
|
||||
{
|
||||
EXIT_IF(bind.descriptor_set_slot != *set_layouts_num);
|
||||
|
||||
set_layouts[*set_layouts_num] = g_render_ctx->GetDescriptorCache()->GetDescriptorSetLayout(
|
||||
stage, bind.storage_buffers.buffers_num, (bind_params.textures2D_without_sampler ? 0 : bind.textures2D.textures_num),
|
||||
(bind_params.textures2D_without_sampler ? bind.textures2D.textures_num : 0), bind.samplers.samplers_num,
|
||||
(bind.gds_pointers.pointers_num > 0 ? 1 : 0));
|
||||
set_layouts[*set_layouts_num] = g_render_ctx->GetDescriptorCache()->GetDescriptorSetLayout(stage, bind, bind_params);
|
||||
(*set_layouts_num)++;
|
||||
}
|
||||
}
|
||||
@@ -2040,6 +2037,8 @@ VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, Re
|
||||
p.vs_shader_id = vs_id;
|
||||
p.params = new PipelineParameters;
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(depth->depth_test_enable && ps_input_info->ps_execute_on_noop);
|
||||
|
||||
p.params->viewport_scale[0] = vp.viewports[0].xscale;
|
||||
p.params->viewport_scale[1] = vp.viewports[0].yscale;
|
||||
p.params->viewport_scale[2] = vp.viewports[0].zscale;
|
||||
@@ -2241,12 +2240,22 @@ static void create_layout(GraphicContext* gctx, int storage_buffers_num, int tex
|
||||
{
|
||||
uint32_t binding_num = 0;
|
||||
|
||||
VkDescriptorSetLayoutBinding ubo_layout_binding[5] = {};
|
||||
ShaderBindResources tmp {};
|
||||
tmp.storage_buffers.buffers_num = storage_buffers_num;
|
||||
tmp.textures2D.textures_num = textures2d_sampled_num + textures2d_storage_num;
|
||||
tmp.samplers.samplers_num = samplers_num;
|
||||
tmp.gds_pointers.pointers_num = gds_buffers_num;
|
||||
|
||||
ShaderCalcBindingIndices(&tmp);
|
||||
|
||||
constexpr uint32_t B_MAX = 5;
|
||||
|
||||
VkDescriptorSetLayoutBinding ubo_layout_binding[B_MAX] = {};
|
||||
|
||||
if (storage_buffers_num > 0)
|
||||
{
|
||||
EXIT_IF(binding_num >= sizeof(ubo_layout_binding) / sizeof(ubo_layout_binding[0]));
|
||||
ubo_layout_binding[binding_num].binding = binding_num;
|
||||
EXIT_IF(binding_num >= B_MAX);
|
||||
ubo_layout_binding[binding_num].binding = tmp.storage_buffers.binding_index;
|
||||
ubo_layout_binding[binding_num].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
ubo_layout_binding[binding_num].descriptorCount = storage_buffers_num;
|
||||
ubo_layout_binding[binding_num].stageFlags = stage;
|
||||
@@ -2256,8 +2265,8 @@ static void create_layout(GraphicContext* gctx, int storage_buffers_num, int tex
|
||||
|
||||
if (textures2d_sampled_num > 0)
|
||||
{
|
||||
EXIT_IF(binding_num >= sizeof(ubo_layout_binding) / sizeof(ubo_layout_binding[0]));
|
||||
ubo_layout_binding[binding_num].binding = binding_num;
|
||||
EXIT_IF(binding_num >= B_MAX);
|
||||
ubo_layout_binding[binding_num].binding = tmp.textures2D.binding_sampled_index;
|
||||
ubo_layout_binding[binding_num].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
ubo_layout_binding[binding_num].descriptorCount = textures2d_sampled_num;
|
||||
ubo_layout_binding[binding_num].stageFlags = stage;
|
||||
@@ -2267,8 +2276,8 @@ static void create_layout(GraphicContext* gctx, int storage_buffers_num, int tex
|
||||
|
||||
if (textures2d_storage_num > 0)
|
||||
{
|
||||
EXIT_IF(binding_num >= sizeof(ubo_layout_binding) / sizeof(ubo_layout_binding[0]));
|
||||
ubo_layout_binding[binding_num].binding = binding_num;
|
||||
EXIT_IF(binding_num >= B_MAX);
|
||||
ubo_layout_binding[binding_num].binding = tmp.textures2D.binding_storage_index;
|
||||
ubo_layout_binding[binding_num].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
ubo_layout_binding[binding_num].descriptorCount = textures2d_storage_num;
|
||||
ubo_layout_binding[binding_num].stageFlags = stage;
|
||||
@@ -2278,8 +2287,8 @@ static void create_layout(GraphicContext* gctx, int storage_buffers_num, int tex
|
||||
|
||||
if (samplers_num > 0)
|
||||
{
|
||||
EXIT_IF(binding_num >= sizeof(ubo_layout_binding) / sizeof(ubo_layout_binding[0]));
|
||||
ubo_layout_binding[binding_num].binding = binding_num;
|
||||
EXIT_IF(binding_num >= B_MAX);
|
||||
ubo_layout_binding[binding_num].binding = tmp.samplers.binding_index;
|
||||
ubo_layout_binding[binding_num].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
ubo_layout_binding[binding_num].descriptorCount = samplers_num;
|
||||
ubo_layout_binding[binding_num].stageFlags = stage;
|
||||
@@ -2289,8 +2298,8 @@ static void create_layout(GraphicContext* gctx, int storage_buffers_num, int tex
|
||||
|
||||
if (gds_buffers_num > 0)
|
||||
{
|
||||
EXIT_IF(binding_num >= sizeof(ubo_layout_binding) / sizeof(ubo_layout_binding[0]));
|
||||
ubo_layout_binding[binding_num].binding = binding_num;
|
||||
EXIT_IF(binding_num >= B_MAX);
|
||||
ubo_layout_binding[binding_num].binding = tmp.gds_pointers.binding_index;
|
||||
ubo_layout_binding[binding_num].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
ubo_layout_binding[binding_num].descriptorCount = gds_buffers_num;
|
||||
ubo_layout_binding[binding_num].stageFlags = stage;
|
||||
@@ -2472,11 +2481,16 @@ 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, VulkanImage** textures2d_sampled,
|
||||
int textures2d_storage_num, VulkanImage** textures2d_storage, int samplers_num,
|
||||
uint64_t* samplers, int gds_buffers_num, VulkanBuffer** gds_buffers)
|
||||
VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, VulkanBuffer** storage_buffers, VulkanImage** textures2d_sampled,
|
||||
VulkanImage** textures2d_storage, uint64_t* samplers, VulkanBuffer** gds_buffers,
|
||||
const ShaderBindResources& bind, const ShaderBindParameters& bind_params)
|
||||
{
|
||||
int storage_buffers_num = bind.storage_buffers.buffers_num;
|
||||
int textures2d_sampled_num = bind_params.textures2d_sampled_num;
|
||||
int textures2d_storage_num = bind_params.textures2d_storage_num;
|
||||
int samplers_num = bind.samplers.samplers_num;
|
||||
int gds_buffers_num = bind.gds_pointers.pointers_num;
|
||||
|
||||
EXIT_IF(storage_buffers_num < 0 || storage_buffers_num > BUFFERS_MAX);
|
||||
EXIT_IF(textures2d_sampled_num < 0 || textures2d_sampled_num > TEXTURES_SAMPLED_MAX);
|
||||
EXIT_IF(textures2d_storage_num < 0 || textures2d_storage_num > TEXTURES_STORAGE_MAX);
|
||||
@@ -2599,15 +2613,17 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, int storage_buf
|
||||
|
||||
int binding_num = 0;
|
||||
|
||||
VkWriteDescriptorSet descriptor_write[5] = {};
|
||||
constexpr uint32_t B_MAX = 5;
|
||||
|
||||
VkWriteDescriptorSet descriptor_write[B_MAX] = {};
|
||||
|
||||
if (storage_buffers_num > 0)
|
||||
{
|
||||
EXIT_IF(binding_num >= static_cast<int>(sizeof(descriptor_write) / sizeof(descriptor_write[0])));
|
||||
EXIT_IF(binding_num >= B_MAX);
|
||||
descriptor_write[binding_num].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_write[binding_num].pNext = nullptr;
|
||||
descriptor_write[binding_num].dstSet = new_set->set;
|
||||
descriptor_write[binding_num].dstBinding = binding_num;
|
||||
descriptor_write[binding_num].dstBinding = bind.storage_buffers.binding_index;
|
||||
descriptor_write[binding_num].dstArrayElement = 0;
|
||||
descriptor_write[binding_num].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
descriptor_write[binding_num].descriptorCount = storage_buffers_num;
|
||||
@@ -2619,11 +2635,11 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, int storage_buf
|
||||
|
||||
if (textures2d_sampled_num > 0)
|
||||
{
|
||||
EXIT_IF(binding_num >= static_cast<int>(sizeof(descriptor_write) / sizeof(descriptor_write[0])));
|
||||
EXIT_IF(binding_num >= B_MAX);
|
||||
descriptor_write[binding_num].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_write[binding_num].pNext = nullptr;
|
||||
descriptor_write[binding_num].dstSet = new_set->set;
|
||||
descriptor_write[binding_num].dstBinding = binding_num;
|
||||
descriptor_write[binding_num].dstBinding = bind.textures2D.binding_sampled_index;
|
||||
descriptor_write[binding_num].dstArrayElement = 0;
|
||||
descriptor_write[binding_num].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
descriptor_write[binding_num].descriptorCount = textures2d_sampled_num;
|
||||
@@ -2635,11 +2651,11 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, int storage_buf
|
||||
|
||||
if (textures2d_storage_num > 0)
|
||||
{
|
||||
EXIT_IF(binding_num >= static_cast<int>(sizeof(descriptor_write) / sizeof(descriptor_write[0])));
|
||||
EXIT_IF(binding_num >= B_MAX);
|
||||
descriptor_write[binding_num].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_write[binding_num].pNext = nullptr;
|
||||
descriptor_write[binding_num].dstSet = new_set->set;
|
||||
descriptor_write[binding_num].dstBinding = binding_num;
|
||||
descriptor_write[binding_num].dstBinding = bind.textures2D.binding_storage_index;
|
||||
descriptor_write[binding_num].dstArrayElement = 0;
|
||||
descriptor_write[binding_num].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
descriptor_write[binding_num].descriptorCount = textures2d_storage_num;
|
||||
@@ -2651,11 +2667,11 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, int storage_buf
|
||||
|
||||
if (samplers_num > 0)
|
||||
{
|
||||
EXIT_IF(binding_num >= static_cast<int>(sizeof(descriptor_write) / sizeof(descriptor_write[0])));
|
||||
EXIT_IF(binding_num >= B_MAX);
|
||||
descriptor_write[binding_num].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_write[binding_num].pNext = nullptr;
|
||||
descriptor_write[binding_num].dstSet = new_set->set;
|
||||
descriptor_write[binding_num].dstBinding = binding_num;
|
||||
descriptor_write[binding_num].dstBinding = bind.samplers.binding_index;
|
||||
descriptor_write[binding_num].dstArrayElement = 0;
|
||||
descriptor_write[binding_num].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
descriptor_write[binding_num].descriptorCount = samplers_num;
|
||||
@@ -2667,11 +2683,11 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, int storage_buf
|
||||
|
||||
if (gds_buffers_num > 0)
|
||||
{
|
||||
EXIT_IF(binding_num >= static_cast<int>(sizeof(descriptor_write) / sizeof(descriptor_write[0])));
|
||||
EXIT_IF(binding_num >= B_MAX);
|
||||
descriptor_write[binding_num].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_write[binding_num].pNext = nullptr;
|
||||
descriptor_write[binding_num].dstSet = new_set->set;
|
||||
descriptor_write[binding_num].dstBinding = binding_num;
|
||||
descriptor_write[binding_num].dstBinding = bind.gds_pointers.binding_index;
|
||||
descriptor_write[binding_num].dstArrayElement = 0;
|
||||
descriptor_write[binding_num].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
descriptor_write[binding_num].descriptorCount = gds_buffers_num;
|
||||
@@ -2772,9 +2788,15 @@ void DescriptorCache::FreeDescriptor(VulkanImage* image)
|
||||
}
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout DescriptorCache::GetDescriptorSetLayout(Stage stage, int storage_buffers_num, int textures2d_sampled_num,
|
||||
int textures2d_storage_num, int samplers_num, int gds_buffers_num)
|
||||
VkDescriptorSetLayout DescriptorCache::GetDescriptorSetLayout(Stage stage, const ShaderBindResources& bind,
|
||||
const ShaderBindParameters& bind_params)
|
||||
{
|
||||
int storage_buffers_num = bind.storage_buffers.buffers_num;
|
||||
int textures2d_sampled_num = bind_params.textures2d_sampled_num;
|
||||
int textures2d_storage_num = bind_params.textures2d_storage_num;
|
||||
int samplers_num = bind.samplers.samplers_num;
|
||||
int gds_buffers_num = bind.gds_pointers.pointers_num;
|
||||
|
||||
EXIT_IF(storage_buffers_num < 0 || storage_buffers_num > BUFFERS_MAX);
|
||||
EXIT_IF(textures2d_sampled_num < 0 || textures2d_sampled_num > TEXTURES_SAMPLED_MAX);
|
||||
EXIT_IF(textures2d_storage_num < 0 || textures2d_storage_num > TEXTURES_STORAGE_MAX);
|
||||
@@ -2826,6 +2848,11 @@ void DeleteDescriptor(TextureVulkanImage* image)
|
||||
g_render_ctx->GetDescriptorCache()->FreeDescriptor(image);
|
||||
}
|
||||
|
||||
void DeleteDescriptor(StorageTextureVulkanImage* image)
|
||||
{
|
||||
g_render_ctx->GetDescriptorCache()->FreeDescriptor(image);
|
||||
}
|
||||
|
||||
void DeleteDescriptor(RenderTextureVulkanImage* image)
|
||||
{
|
||||
g_render_ctx->GetDescriptorCache()->FreeDescriptor(image);
|
||||
@@ -3138,11 +3165,17 @@ static void PrepareStorageBuffers(const ShaderStorageResources& storage_buffers,
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
static void PrepareTextures(const ShaderTextureResources& textures, VulkanImage** images, uint32_t** sgprs, bool with_sampler)
|
||||
static void PrepareTextures(const ShaderTextureResources& textures, VulkanImage** images_sampled, VulkanImage** images_storage,
|
||||
uint32_t** sgprs, const bool* without_sampler)
|
||||
{
|
||||
EXIT_IF(images == nullptr);
|
||||
EXIT_IF(images_sampled == nullptr);
|
||||
EXIT_IF(images_storage == nullptr);
|
||||
EXIT_IF(sgprs == nullptr);
|
||||
EXIT_IF(*sgprs == nullptr);
|
||||
EXIT_IF(without_sampler == nullptr);
|
||||
|
||||
int index_sampled = 0;
|
||||
int index_storage = 0;
|
||||
|
||||
for (int i = 0; i < textures.textures_num; i++)
|
||||
{
|
||||
@@ -3172,7 +3205,12 @@ static void PrepareTextures(const ShaderTextureResources& textures, VulkanImage*
|
||||
EXIT_NOT_IMPLEMENTED(r.MinLodWarn() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.CounterBankId() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.LodHdwCntEn() != false);
|
||||
EXIT_NOT_IMPLEMENTED(r.MemoryType() != 0x10);
|
||||
EXIT_NOT_IMPLEMENTED(r.MemoryType() != 0x10 && r.MemoryType() != 0x6d);
|
||||
|
||||
bool read_only = (r.MemoryType() == 0x10);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(read_only && !(textures.usages[i] == ShaderTextureUsage::ReadOnly));
|
||||
// EXIT_NOT_IMPLEMENTED(!read_only && !(textures.usages[i] == ShaderTextureUsage::ReadWrite));
|
||||
|
||||
auto addr = r.Base();
|
||||
uint32_t size = 0;
|
||||
@@ -3192,17 +3230,34 @@ static void PrepareTextures(const ShaderTextureResources& textures, VulkanImage*
|
||||
|
||||
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));
|
||||
if (without_sampler[i])
|
||||
{
|
||||
StorageTextureObject vulkan_texture_info(r.Dfmt(), r.Nfmt(), width, height, pitch, levels, tile, neo, swizzle);
|
||||
|
||||
tex = static_cast<TextureVulkanImage*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), addr, size, vulkan_texture_info));
|
||||
tex = static_cast<StorageTextureVulkanImage*>(
|
||||
GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), addr, size, vulkan_texture_info));
|
||||
} else
|
||||
{
|
||||
TextureObject vulkan_texture_info(r.Dfmt(), r.Nfmt(), width, height, pitch, levels, tile, neo, swizzle);
|
||||
|
||||
tex =
|
||||
static_cast<TextureVulkanImage*>(GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), addr, size, vulkan_texture_info));
|
||||
}
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(tex == nullptr);
|
||||
|
||||
images[i] = tex;
|
||||
|
||||
r.UpdateAddress(i);
|
||||
if (without_sampler[i])
|
||||
{
|
||||
images_storage[index_storage] = tex;
|
||||
r.UpdateAddress(index_storage);
|
||||
index_storage++;
|
||||
} else
|
||||
{
|
||||
images_sampled[index_sampled] = tex;
|
||||
r.UpdateAddress(index_sampled);
|
||||
index_sampled++;
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED((r.Base() >> 32u) != 0);
|
||||
|
||||
@@ -3243,16 +3298,16 @@ static void PrepareSamplers(const ShaderSamplerResources& samplers, uint64_t* sa
|
||||
EXIT_NOT_IMPLEMENTED(r.TruncCoord() != false);
|
||||
EXIT_NOT_IMPLEMENTED(r.DisableCubeWrap() != false);
|
||||
EXIT_NOT_IMPLEMENTED(r.FilterMode() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.MinLod() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.MaxLod() != 4095);
|
||||
// EXIT_NOT_IMPLEMENTED(r.MinLod() != 0);
|
||||
// EXIT_NOT_IMPLEMENTED(r.MaxLod() != 4095);
|
||||
EXIT_NOT_IMPLEMENTED(r.PerfMip() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.PerfZ() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.LodBias() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.LodBiasSec() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.XyMagFilter() != 1);
|
||||
EXIT_NOT_IMPLEMENTED(r.XyMinFilter() != 1);
|
||||
// EXIT_NOT_IMPLEMENTED(r.XyMagFilter() != 1);
|
||||
// EXIT_NOT_IMPLEMENTED(r.XyMinFilter() != 1);
|
||||
EXIT_NOT_IMPLEMENTED(r.ZFilter() != 1);
|
||||
EXIT_NOT_IMPLEMENTED(r.MipFilter() != 0 && r.MipFilter() != 2);
|
||||
// EXIT_NOT_IMPLEMENTED(r.MipFilter() != 0 && r.MipFilter() != 2);
|
||||
EXIT_NOT_IMPLEMENTED(r.BorderColorPtr() != 0);
|
||||
EXIT_NOT_IMPLEMENTED(r.BorderColorType() != 0);
|
||||
|
||||
@@ -3297,9 +3352,9 @@ static void BindDescriptors(VkCommandBuffer vk_buffer, VkPipelineBindPoint pipel
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(bind.push_constant_size > DescriptorCache::PUSH_CONSTANTS_MAX * 4);
|
||||
EXIT_NOT_IMPLEMENTED(bind.storage_buffers.buffers_num > DescriptorCache::BUFFERS_MAX);
|
||||
EXIT_NOT_IMPLEMENTED(
|
||||
(bind_params.textures2D_without_sampler && bind.textures2D.textures_num > DescriptorCache::TEXTURES_STORAGE_MAX) ||
|
||||
(!bind_params.textures2D_without_sampler && bind.textures2D.textures_num > DescriptorCache::TEXTURES_SAMPLED_MAX));
|
||||
EXIT_NOT_IMPLEMENTED((bind_params.textures2d_storage_num > DescriptorCache::TEXTURES_STORAGE_MAX) ||
|
||||
(bind_params.textures2d_sampled_num > DescriptorCache::TEXTURES_SAMPLED_MAX));
|
||||
EXIT_NOT_IMPLEMENTED(bind_params.textures2d_storage_num + bind_params.textures2d_sampled_num != bind.textures2D.textures_num);
|
||||
EXIT_NOT_IMPLEMENTED(bind.samplers.samplers_num > DescriptorCache::SAMPLERS_MAX);
|
||||
|
||||
VulkanBuffer* storage_buffers[DescriptorCache::BUFFERS_MAX];
|
||||
@@ -3318,13 +3373,7 @@ static void BindDescriptors(VkCommandBuffer vk_buffer, VkPipelineBindPoint pipel
|
||||
}
|
||||
if (bind.textures2D.textures_num > 0)
|
||||
{
|
||||
if (bind_params.textures2D_without_sampler)
|
||||
{
|
||||
PrepareTextures(bind.textures2D, textures2d_storage, &sgprs_ptr, false);
|
||||
} else
|
||||
{
|
||||
PrepareTextures(bind.textures2D, textures2d_sampled, &sgprs_ptr, true);
|
||||
}
|
||||
PrepareTextures(bind.textures2D, textures2d_sampled, textures2d_storage, &sgprs_ptr, bind_params.textures2d_without_sampler);
|
||||
}
|
||||
if (bind.samplers.samplers_num > 0)
|
||||
{
|
||||
@@ -3339,10 +3388,7 @@ static void BindDescriptors(VkCommandBuffer vk_buffer, VkPipelineBindPoint pipel
|
||||
EXIT_IF(bind.push_constant_size != (sgprs_ptr - sgprs) * 4);
|
||||
|
||||
auto* descriptor_set = g_render_ctx->GetDescriptorCache()->GetDescriptor(
|
||||
stage, bind.storage_buffers.buffers_num, storage_buffers,
|
||||
(bind_params.textures2D_without_sampler ? 0 : bind.textures2D.textures_num), textures2d_sampled,
|
||||
(bind_params.textures2D_without_sampler ? bind.textures2D.textures_num : 0), textures2d_storage, bind.samplers.samplers_num,
|
||||
samplers, (gds_buffer != nullptr ? 1 : 0), &gds_buffer);
|
||||
stage, storage_buffers, textures2d_sampled, textures2d_storage, samplers, &gds_buffer, bind, bind_params);
|
||||
|
||||
EXIT_IF(descriptor_set == nullptr);
|
||||
vkCmdBindDescriptorSets(vk_buffer, pipeline_bind_point, layout, bind.descriptor_set_slot, 1, &descriptor_set->set, 0, nullptr);
|
||||
@@ -3565,8 +3611,8 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HardwareContext* ctx, Us
|
||||
{
|
||||
case 4: vkCmdDraw(vk_buffer, index_count, 1, 0, 0); break;
|
||||
case 17:
|
||||
EXIT_NOT_IMPLEMENTED(!(vertex_shader_info.vs_embedded && vertex_shader_info.vs_embedded_id == 0 && index_count == 3 &&
|
||||
vs_input_info.buffers_num == 0));
|
||||
EXIT_NOT_IMPLEMENTED(!(/*vertex_shader_info.vs_embedded && vertex_shader_info.vs_embedded_id == 0 &&*/
|
||||
index_count == 3 && vs_input_info.buffers_num == 0));
|
||||
vkCmdDraw(vk_buffer, 4, 1, 0, 0);
|
||||
break;
|
||||
case 19:
|
||||
@@ -3662,7 +3708,7 @@ void GraphicsRenderRenderTextureBarrier(CommandBuffer* buffer, uint64_t vaddr, u
|
||||
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.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
|
||||
image_memory_barrier.subresourceRange.layerCount = 1;
|
||||
|
||||
@@ -4221,7 +4267,7 @@ VulkanFramebuffer* CommandBuffer::BeginRenderPass(RenderColorInfo* color, Render
|
||||
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.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
|
||||
image_memory_barrier.subresourceRange.layerCount = 1;
|
||||
|
||||
|
||||
@@ -937,6 +937,8 @@ void CommandProcessor::Run(uint32_t* data, uint32_t num_dw)
|
||||
|
||||
auto s = pfunc(this, cmd_id, cmd, dw, num_dw);
|
||||
|
||||
// printf("\t %05" PRIx32 ": %u\n", num_dw - dw, s);
|
||||
|
||||
cmd += s;
|
||||
dw -= s + 1;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,14 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
void* DepthStencilBufferObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem) const
|
||||
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("DepthStencilBufferObject::update_func");
|
||||
}
|
||||
|
||||
static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("DepthStencilBufferObject::Create");
|
||||
|
||||
@@ -22,9 +28,9 @@ void* DepthStencilBufferObject::Create(GraphicContext* ctx, const uint64_t* vadd
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
auto pixel_format = static_cast<VkFormat>(params[PARAM_FORMAT]);
|
||||
auto width = params[PARAM_WIDTH];
|
||||
auto height = params[PARAM_HEIGHT];
|
||||
auto pixel_format = static_cast<VkFormat>(params[DepthStencilBufferObject::PARAM_FORMAT]);
|
||||
auto width = params[DepthStencilBufferObject::PARAM_WIDTH];
|
||||
auto height = params[DepthStencilBufferObject::PARAM_HEIGHT];
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(pixel_format == VK_FORMAT_UNDEFINED);
|
||||
EXIT_NOT_IMPLEMENTED(width == 0);
|
||||
@@ -74,7 +80,7 @@ void* DepthStencilBufferObject::Create(GraphicContext* ctx, const uint64_t* vadd
|
||||
|
||||
// EXIT_NOT_IMPLEMENTED(mem->requirements.size > *size);
|
||||
|
||||
GetUpdateFunc()(ctx, params, vk_obj, vaddr, size, vaddr_num);
|
||||
update_func(ctx, params, vk_obj, vaddr, size, vaddr_num);
|
||||
|
||||
VkImageViewCreateInfo create_info {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
@@ -102,18 +108,6 @@ void* DepthStencilBufferObject::Create(GraphicContext* ctx, const uint64_t* vadd
|
||||
return vk_obj;
|
||||
}
|
||||
|
||||
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("DepthStencilBufferObject::update_func");
|
||||
}
|
||||
|
||||
bool DepthStencilBufferObject::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_HTILE] == other[PARAM_HTILE]);
|
||||
}
|
||||
|
||||
static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("DepthStencilBufferObject::delete_func");
|
||||
@@ -134,6 +128,17 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
|
||||
delete vk_obj;
|
||||
}
|
||||
|
||||
bool DepthStencilBufferObject::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_HTILE] == other[PARAM_HTILE]);
|
||||
}
|
||||
|
||||
GpuObject::create_func_t DepthStencilBufferObject::GetCreateFunc() const
|
||||
{
|
||||
return create_func;
|
||||
}
|
||||
|
||||
GpuObject::delete_func_t DepthStencilBufferObject::GetDeleteFunc() const
|
||||
{
|
||||
return delete_func;
|
||||
|
||||
@@ -120,9 +120,8 @@ private:
|
||||
|
||||
struct ObjectInfo
|
||||
{
|
||||
void* obj = nullptr;
|
||||
GpuMemoryObject object;
|
||||
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;
|
||||
@@ -378,7 +377,13 @@ static uint64_t calc_hash(const uint8_t* buf, uint64_t size)
|
||||
|
||||
void GpuMemory::Link(int id1, int id2, OverlapType rel)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(rel != OverlapType::Equals);
|
||||
OverlapType other_rel = OverlapType::None;
|
||||
switch (rel)
|
||||
{
|
||||
case OverlapType::Equals: other_rel = OverlapType::Equals; break;
|
||||
case OverlapType::IsContainedWithin: other_rel = OverlapType::Contains; break;
|
||||
default: EXIT("invalid rel: %s\n", Core::EnumName(rel).C_Str());
|
||||
}
|
||||
|
||||
auto& h1 = m_objects[id1];
|
||||
EXIT_IF(h1.free);
|
||||
@@ -386,11 +391,11 @@ void GpuMemory::Link(int id1, int id2, OverlapType rel)
|
||||
auto& h2 = m_objects[id2];
|
||||
EXIT_IF(h2.free);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(!h1.others.IsEmpty());
|
||||
EXIT_NOT_IMPLEMENTED(!h2.others.IsEmpty());
|
||||
// EXIT_NOT_IMPLEMENTED(!h1.others.IsEmpty());
|
||||
// EXIT_NOT_IMPLEMENTED(!h2.others.IsEmpty());
|
||||
|
||||
h1.others.Add({rel, id2});
|
||||
h2.others.Add({rel, id1});
|
||||
h2.others.Add({other_rel, id1});
|
||||
}
|
||||
|
||||
void GpuMemory::Update(GraphicContext* ctx, ObjectInfo& o, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, const uint64_t* hash)
|
||||
@@ -400,8 +405,8 @@ void GpuMemory::Update(GraphicContext* ctx, ObjectInfo& o, const uint64_t* vaddr
|
||||
{
|
||||
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(),
|
||||
vaddr[vi], size[vi]);
|
||||
printf("Update (CPU -> GPU): type = %s, vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 "\n",
|
||||
Core::EnumName(o.object.type).C_Str(), vaddr[vi], size[vi]);
|
||||
need_update = true;
|
||||
o.hash[vi] = hash[vi];
|
||||
}
|
||||
@@ -409,7 +414,7 @@ void GpuMemory::Update(GraphicContext* ctx, ObjectInfo& o, const uint64_t* vaddr
|
||||
if (need_update)
|
||||
{
|
||||
EXIT_IF(o.update_func == nullptr);
|
||||
o.update_func(ctx, o.params, o.obj, vaddr, size, vaddr_num);
|
||||
o.update_func(ctx, o.params, o.object.obj, vaddr, size, vaddr_num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -436,8 +441,9 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, const uint64_t* vaddr, const
|
||||
}
|
||||
}
|
||||
|
||||
bool overlap = false;
|
||||
bool delete_all = false;
|
||||
bool overlap = false;
|
||||
bool delete_all = false;
|
||||
bool create_from_objects = false;
|
||||
|
||||
auto others = FindBlocks(vaddr, size, vaddr_num);
|
||||
|
||||
@@ -448,7 +454,7 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, const uint64_t* vaddr, const
|
||||
auto& h = m_objects[obj.object_id];
|
||||
EXIT_IF(h.free);
|
||||
auto& o = h.info;
|
||||
if (obj.relation == OverlapType::Equals && o.type == info.type && info.Equal(o.params))
|
||||
if (obj.relation == OverlapType::Equals && o.object.type == info.type && info.Equal(o.params))
|
||||
{
|
||||
Update(ctx, o, vaddr, size, vaddr_num, hash);
|
||||
|
||||
@@ -457,7 +463,7 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, const uint64_t* vaddr, const
|
||||
o.in_use = true;
|
||||
o.read_only = info.read_only;
|
||||
o.check_hash = info.check_hash;
|
||||
return o.obj;
|
||||
return o.object.obj;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,7 +474,7 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, const uint64_t* vaddr, const
|
||||
EXIT_IF(h.free);
|
||||
auto& o = h.info;
|
||||
|
||||
switch (ObjectsRelation(o.type, obj.relation, info.type))
|
||||
switch (ObjectsRelation(o.object.type, obj.relation, info.type))
|
||||
{
|
||||
case ObjectsRelation(GpuMemoryObjectType::StorageBuffer, OverlapType::Equals, GpuMemoryObjectType::RenderTexture):
|
||||
case ObjectsRelation(GpuMemoryObjectType::VideoOutBuffer, OverlapType::Equals, GpuMemoryObjectType::StorageBuffer):
|
||||
@@ -482,17 +488,23 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, const uint64_t* vaddr, const
|
||||
delete_all = true;
|
||||
break;
|
||||
}
|
||||
case ObjectsRelation(GpuMemoryObjectType::StorageTexture, OverlapType::Equals, GpuMemoryObjectType::Texture):
|
||||
{
|
||||
overlap = true;
|
||||
create_from_objects = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
EXIT("unknown relation: %s - %s - %s\n", Core::EnumName(o.type).C_Str(), Core::EnumName(obj.relation).C_Str(),
|
||||
EXIT("unknown relation: %s - %s - %s\n", Core::EnumName(o.object.type).C_Str(), Core::EnumName(obj.relation).C_Str(),
|
||||
Core::EnumName(info.type).C_Str());
|
||||
}
|
||||
} else
|
||||
{
|
||||
OverlapType rel = others.At(0).relation;
|
||||
GpuMemoryObjectType type = m_objects[others.At(0).object_id].info.type;
|
||||
GpuMemoryObjectType type = m_objects[others.At(0).object_id].info.object.type;
|
||||
for (const auto& obj: others)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(rel != obj.relation || type != m_objects[obj.object_id].info.type);
|
||||
EXIT_NOT_IMPLEMENTED(rel != obj.relation || type != m_objects[obj.object_id].info.object.type);
|
||||
}
|
||||
|
||||
switch (ObjectsRelation(type, rel, info.type)) // NOLINT
|
||||
@@ -500,6 +512,10 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, const uint64_t* vaddr, const
|
||||
case ObjectsRelation(GpuMemoryObjectType::Label, OverlapType::IsContainedWithin, GpuMemoryObjectType::StorageBuffer):
|
||||
delete_all = true;
|
||||
break;
|
||||
case ObjectsRelation(GpuMemoryObjectType::RenderTexture, OverlapType::IsContainedWithin, GpuMemoryObjectType::Texture):
|
||||
overlap = true;
|
||||
create_from_objects = true;
|
||||
break;
|
||||
default:
|
||||
EXIT("unknown relation: %s - %s - %s\n", Core::EnumName(type).C_Str(), Core::EnumName(rel).C_Str(),
|
||||
Core::EnumName(info.type).C_Str());
|
||||
@@ -529,13 +545,29 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, const uint64_t* vaddr, const
|
||||
o.params[i] = info.params[i];
|
||||
}
|
||||
|
||||
o.type = info.type;
|
||||
o.obj = nullptr;
|
||||
o.object.type = info.type;
|
||||
o.object.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);
|
||||
|
||||
if (create_from_objects)
|
||||
{
|
||||
Vector<GpuMemoryObject> objects;
|
||||
for (const auto& obj: others)
|
||||
{
|
||||
const auto& o2 = m_objects[obj.object_id].info;
|
||||
objects.Add(o2.object);
|
||||
}
|
||||
auto create_func = info.GetCreateFromObjectsFunc();
|
||||
EXIT_IF(create_func == nullptr);
|
||||
o.object.obj = create_func(ctx, o.params, objects, &o.mem);
|
||||
} else
|
||||
{
|
||||
o.object.obj = info.GetCreateFunc()(ctx, o.params, vaddr, size, vaddr_num, &o.mem);
|
||||
}
|
||||
|
||||
o.write_back_func = info.GetWriteBackFunc();
|
||||
o.delete_func = info.GetDeleteFunc();
|
||||
o.update_func = info.GetUpdateFunc();
|
||||
@@ -574,12 +606,13 @@ void* GpuMemory::CreateObject(GraphicContext* ctx, const uint64_t* vaddr, const
|
||||
|
||||
if (overlap)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(others.Size() != 1);
|
||||
|
||||
Link(index, others.At(0).object_id, others.At(0).relation);
|
||||
for (const auto& obj: others)
|
||||
{
|
||||
Link(index, obj.object_id, obj.relation);
|
||||
}
|
||||
}
|
||||
|
||||
return o.obj;
|
||||
return o.object.obj;
|
||||
}
|
||||
|
||||
Vector<GpuMemoryObject> GpuMemory::FindObjects(const uint64_t* vaddr, const uint64_t* size, int vaddr_num)
|
||||
@@ -603,10 +636,10 @@ Vector<GpuMemoryObject> GpuMemory::FindObjects(const uint64_t* vaddr, const uint
|
||||
{
|
||||
const auto& h = m_objects[obj.object_id];
|
||||
EXIT_IF(h.free);
|
||||
printf("\t %s, %d, %s\n", Core::EnumName(obj.relation).C_Str(), obj.object_id, Core::EnumName(h.info.type).C_Str());
|
||||
printf("\t %s, %d, %s\n", Core::EnumName(obj.relation).C_Str(), obj.object_id, Core::EnumName(h.info.object.type).C_Str());
|
||||
if (obj.relation == OverlapType::Equals)
|
||||
{
|
||||
ret.Add({h.info.type, h.info.obj});
|
||||
ret.Add(h.info.object);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,13 +667,13 @@ void GpuMemory::ResetHash(GraphicContext* /*ctx*/, const uint64_t* vaddr, const
|
||||
EXIT_IF(h.free);
|
||||
|
||||
auto& o = h.info;
|
||||
if (o.type == type)
|
||||
if (o.object.type == type)
|
||||
{
|
||||
for (int vi = 0; vi < 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(), vaddr[vi], size[vi], o.hash[vi], new_hash);
|
||||
Core::EnumName(o.object.type).C_Str(), vaddr[vi], size[vi], o.hash[vi], new_hash);
|
||||
|
||||
o.hash[vi] = new_hash;
|
||||
}
|
||||
@@ -699,10 +732,10 @@ void GpuMemory::Free(GraphicContext* ctx, int object_id)
|
||||
// EXIT_IF(block.free);
|
||||
for (int vi = 0; vi < block.vaddr_num; vi++)
|
||||
{
|
||||
printf("Delete: type = %s, vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 "\n", Core::EnumName(o.type).C_Str(),
|
||||
printf("Delete: type = %s, vaddr = 0x%016" PRIx64 ", size = 0x%016" PRIx64 "\n", Core::EnumName(o.object.type).C_Str(),
|
||||
block.vaddr[vi], block.size[vi]);
|
||||
}
|
||||
o.delete_func(ctx, o.obj, &o.mem);
|
||||
o.delete_func(ctx, o.object.obj, &o.mem);
|
||||
}
|
||||
h.free = true;
|
||||
DeleteBlock(&h.block);
|
||||
@@ -840,7 +873,7 @@ void GpuMemory::WriteBack(GraphicContext* ctx)
|
||||
auto& block = h.block;
|
||||
// EXIT_IF(block.free);
|
||||
|
||||
o.write_back_func(ctx, o.obj, block.vaddr, block.size, block.vaddr_num);
|
||||
o.write_back_func(ctx, o.object.obj, block.vaddr, block.size, block.vaddr_num);
|
||||
|
||||
for (int vi = 0; vi < block.vaddr_num; vi++)
|
||||
{
|
||||
@@ -853,7 +886,7 @@ void GpuMemory::WriteBack(GraphicContext* ctx)
|
||||
|
||||
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(), block.vaddr[vi], block.size[vi], o.hash[vi], new_hash);
|
||||
Core::EnumName(o.object.type).C_Str(), block.vaddr[vi], block.size[vi], o.hash[vi], new_hash);
|
||||
|
||||
o.hash[vi] = new_hash;
|
||||
}
|
||||
@@ -889,7 +922,7 @@ void GpuMemory::Flush(GraphicContext* ctx)
|
||||
auto& o = h.info;
|
||||
|
||||
EXIT_IF(o.update_func == nullptr);
|
||||
o.update_func(ctx, o.params, o.obj, block.vaddr, block.size, block.vaddr_num);
|
||||
o.update_func(ctx, o.params, o.object.obj, block.vaddr, block.size, block.vaddr_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1012,13 +1045,13 @@ void GpuMemory::DbgDbDump()
|
||||
(r.block.vaddr_num > 0 ? m_db_add_object->BindString(":size", hex(r.block.size[0])) : m_db_add_object->BindNull(":size"));
|
||||
(r.block.vaddr_num > 1 ? m_db_add_object->BindString(":size2", hex(r.block.size[1])) : m_db_add_object->BindNull(":size2"));
|
||||
(r.block.vaddr_num > 2 ? m_db_add_object->BindString(":size3", hex(r.block.size[2])) : m_db_add_object->BindNull(":size3"));
|
||||
m_db_add_object->BindString(":obj", hex(r.info.obj));
|
||||
m_db_add_object->BindString(":obj", hex(r.info.object.obj));
|
||||
int param0_index = m_db_add_object->GetIndex(":param0");
|
||||
for (int i = 0; i < GpuObject::PARAMS_MAX; i++)
|
||||
{
|
||||
m_db_add_object->BindInt64(param0_index + i, static_cast<int64_t>(r.info.params[i]));
|
||||
}
|
||||
m_db_add_object->BindString(":type", Core::EnumName(r.info.type).C_Str());
|
||||
m_db_add_object->BindString(":type", Core::EnumName(r.info.object.type).C_Str());
|
||||
int hash0_index = m_db_add_object->GetIndex(":hash");
|
||||
for (int i = 0; i < VADDR_BLOCKS_MAX; i++)
|
||||
{
|
||||
@@ -1120,7 +1153,7 @@ void GpuMemory::DbgDump()
|
||||
}
|
||||
}
|
||||
auto& o = h.info;
|
||||
printf("\t type = %s\n", Core::EnumName(o.type).C_Str());
|
||||
printf("\t type = %s\n", Core::EnumName(o.object.type).C_Str());
|
||||
for (int vi = 0; vi < block.vaddr_num; vi++)
|
||||
{
|
||||
printf("\t hash = 0x%016" PRIx64 "\n", o.hash[vi]);
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
void* IndexBufferGpuObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const
|
||||
static void* create_func(GraphicContext* ctx, const uint64_t* /*params*/, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("IndexBufferGpuObject::Create");
|
||||
|
||||
@@ -59,11 +60,6 @@ static void update_func(GraphicContext* /*ctx*/, const uint64_t* /*params*/, voi
|
||||
KYTY_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
bool IndexBufferGpuObject::Equal(const uint64_t* /*other*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* /*mem*/)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("IndexBufferGpuObject::delete_func");
|
||||
@@ -79,6 +75,16 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* /*mem*/)
|
||||
delete vk_obj;
|
||||
}
|
||||
|
||||
bool IndexBufferGpuObject::Equal(const uint64_t* /*other*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
GpuObject::create_func_t IndexBufferGpuObject::GetCreateFunc() const
|
||||
{
|
||||
return create_func;
|
||||
}
|
||||
|
||||
GpuObject::delete_func_t IndexBufferGpuObject::GetDeleteFunc() const
|
||||
{
|
||||
return delete_func;
|
||||
|
||||
@@ -330,7 +330,8 @@ void LabelSet(CommandBuffer* buffer, Label* label)
|
||||
g_label_manager->Set(buffer, label);
|
||||
}
|
||||
|
||||
void* LabelGpuObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* /*mem*/) const
|
||||
static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* /*mem*/)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("LabelGpuObject::Create");
|
||||
|
||||
@@ -338,15 +339,15 @@ void* LabelGpuObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const u
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(*size != 8 && *size != 4);
|
||||
|
||||
auto value = params[PARAM_VALUE];
|
||||
auto callback_1 = reinterpret_cast<LabelGpuObject::callback_t>(params[PARAM_CALLBACK_1]);
|
||||
auto callback_2 = reinterpret_cast<LabelGpuObject::callback_t>(params[PARAM_CALLBACK_2]);
|
||||
auto value = params[LabelGpuObject::PARAM_VALUE];
|
||||
auto callback_1 = reinterpret_cast<LabelGpuObject::callback_t>(params[LabelGpuObject::PARAM_CALLBACK_1]);
|
||||
auto callback_2 = reinterpret_cast<LabelGpuObject::callback_t>(params[LabelGpuObject::PARAM_CALLBACK_2]);
|
||||
|
||||
auto* label_obj =
|
||||
(*size == 8 ? LabelCreate(ctx, reinterpret_cast<uint64_t*>(*vaddr), value, callback_1, callback_2, params + PARAM_ARG_1)
|
||||
: (*size == 4 ? LabelCreate(ctx, reinterpret_cast<uint32_t*>(*vaddr), static_cast<uint32_t>(value), callback_1,
|
||||
callback_2, params + PARAM_ARG_1)
|
||||
: nullptr));
|
||||
auto* label_obj = (*size == 8 ? LabelCreate(ctx, reinterpret_cast<uint64_t*>(*vaddr), value, callback_1, callback_2,
|
||||
params + LabelGpuObject::PARAM_ARG_1)
|
||||
: (*size == 4 ? LabelCreate(ctx, reinterpret_cast<uint32_t*>(*vaddr), static_cast<uint32_t>(value),
|
||||
callback_1, callback_2, params + LabelGpuObject::PARAM_ARG_1)
|
||||
: nullptr));
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(label_obj == nullptr);
|
||||
|
||||
@@ -361,14 +362,6 @@ static void update_func(GraphicContext* /*ctx*/, const uint64_t* /*params*/, voi
|
||||
KYTY_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
bool LabelGpuObject::Equal(const uint64_t* other) const
|
||||
{
|
||||
return (params[PARAM_VALUE] == other[PARAM_VALUE] && params[PARAM_CALLBACK_1] == other[PARAM_CALLBACK_1] &&
|
||||
params[PARAM_CALLBACK_2] == other[PARAM_CALLBACK_2] && params[PARAM_ARG_1] == other[PARAM_ARG_1] &&
|
||||
params[PARAM_ARG_2] == other[PARAM_ARG_2] && params[PARAM_ARG_3] == other[PARAM_ARG_3] &&
|
||||
params[PARAM_ARG_4] == other[PARAM_ARG_4]);
|
||||
}
|
||||
|
||||
static void delete_func(GraphicContext* /*ctx*/, void* obj, VulkanMemory* /*mem*/)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("LabelGpuObject::delete_func");
|
||||
@@ -380,6 +373,19 @@ static void delete_func(GraphicContext* /*ctx*/, void* obj, VulkanMemory* /*mem*
|
||||
LabelDelete(label_obj);
|
||||
}
|
||||
|
||||
bool LabelGpuObject::Equal(const uint64_t* other) const
|
||||
{
|
||||
return (params[PARAM_VALUE] == other[PARAM_VALUE] && params[PARAM_CALLBACK_1] == other[PARAM_CALLBACK_1] &&
|
||||
params[PARAM_CALLBACK_2] == other[PARAM_CALLBACK_2] && params[PARAM_ARG_1] == other[PARAM_ARG_1] &&
|
||||
params[PARAM_ARG_2] == other[PARAM_ARG_2] && params[PARAM_ARG_3] == other[PARAM_ARG_3] &&
|
||||
params[PARAM_ARG_4] == other[PARAM_ARG_4]);
|
||||
}
|
||||
|
||||
GpuObject::create_func_t LabelGpuObject::GetCreateFunc() const
|
||||
{
|
||||
return create_func;
|
||||
}
|
||||
|
||||
GpuObject::delete_func_t LabelGpuObject::GetDeleteFunc() const
|
||||
{
|
||||
return delete_func;
|
||||
|
||||
@@ -14,7 +14,60 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
void* RenderTextureObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("RenderTextureObject::Create");
|
||||
|
||||
@@ -22,9 +75,9 @@ void* RenderTextureObject::Create(GraphicContext* ctx, const uint64_t* vaddr, co
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
auto pixel_format = params[PARAM_FORMAT];
|
||||
auto width = params[PARAM_WIDTH];
|
||||
auto height = params[PARAM_HEIGHT];
|
||||
auto pixel_format = params[RenderTextureObject::PARAM_FORMAT];
|
||||
auto width = params[RenderTextureObject::PARAM_WIDTH];
|
||||
auto height = params[RenderTextureObject::PARAM_HEIGHT];
|
||||
|
||||
VkFormat vk_format = VK_FORMAT_UNDEFINED;
|
||||
|
||||
@@ -89,7 +142,7 @@ void* RenderTextureObject::Create(GraphicContext* ctx, const uint64_t* vaddr, co
|
||||
|
||||
// EXIT_NOT_IMPLEMENTED(mem->requirements.size > *size);
|
||||
|
||||
GetUpdateFunc()(ctx, params, vk_obj, vaddr, size, vaddr_num);
|
||||
update_func(ctx, params, vk_obj, vaddr, size, vaddr_num);
|
||||
|
||||
VkImageViewCreateInfo create_info {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
@@ -115,65 +168,6 @@ void* RenderTextureObject::Create(GraphicContext* ctx, const uint64_t* vaddr, co
|
||||
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");
|
||||
@@ -196,6 +190,18 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
|
||||
delete vk_obj;
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
GpuObject::create_func_t RenderTextureObject::GetCreateFunc() const
|
||||
{
|
||||
return create_func;
|
||||
}
|
||||
|
||||
GpuObject::delete_func_t RenderTextureObject::GetDeleteFunc() const
|
||||
{
|
||||
return delete_func;
|
||||
|
||||
@@ -12,31 +12,6 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
void* StorageBufferGpuObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem) const
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("StorageBufferGpuObject::Create");
|
||||
|
||||
EXIT_IF(vaddr_num != 1 || size == nullptr || vaddr == nullptr || *vaddr == 0);
|
||||
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
auto* vk_obj = new VulkanBuffer;
|
||||
|
||||
vk_obj->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
vk_obj->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
|
||||
vk_obj->buffer = nullptr;
|
||||
|
||||
VulkanCreateBuffer(ctx, *size, vk_obj);
|
||||
EXIT_NOT_IMPLEMENTED(vk_obj->buffer == nullptr);
|
||||
|
||||
GetUpdateFunc()(ctx, params, vk_obj, vaddr, size, vaddr_num);
|
||||
|
||||
return vk_obj;
|
||||
}
|
||||
|
||||
static void update_func(GraphicContext* ctx, const uint64_t* /*params*/, void* obj, const uint64_t* vaddr, const uint64_t* size,
|
||||
int vaddr_num)
|
||||
{
|
||||
@@ -56,9 +31,29 @@ static void update_func(GraphicContext* ctx, const uint64_t* /*params*/, void* o
|
||||
VulkanUnmapMemory(ctx, &vk_obj->memory);
|
||||
}
|
||||
|
||||
bool StorageBufferGpuObject::Equal(const uint64_t* other) const
|
||||
static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem)
|
||||
{
|
||||
return params[0] == other[0] && params[1] == other[1];
|
||||
KYTY_PROFILER_BLOCK("StorageBufferGpuObject::Create");
|
||||
|
||||
EXIT_IF(vaddr_num != 1 || size == nullptr || vaddr == nullptr || *vaddr == 0);
|
||||
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
auto* vk_obj = new VulkanBuffer;
|
||||
|
||||
vk_obj->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
vk_obj->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
|
||||
vk_obj->buffer = nullptr;
|
||||
|
||||
VulkanCreateBuffer(ctx, *size, vk_obj);
|
||||
EXIT_NOT_IMPLEMENTED(vk_obj->buffer == nullptr);
|
||||
|
||||
update_func(ctx, params, vk_obj, vaddr, size, vaddr_num);
|
||||
|
||||
return vk_obj;
|
||||
}
|
||||
|
||||
static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* /*mem*/)
|
||||
@@ -103,6 +98,16 @@ static void write_back(GraphicContext* ctx, void* obj, const uint64_t* vaddr, co
|
||||
KYTY_PROFILER_END_BLOCK;
|
||||
}
|
||||
|
||||
bool StorageBufferGpuObject::Equal(const uint64_t* other) const
|
||||
{
|
||||
return params[0] == other[0] && params[1] == other[1];
|
||||
}
|
||||
|
||||
GpuObject::create_func_t StorageBufferGpuObject::GetCreateFunc() const
|
||||
{
|
||||
return create_func;
|
||||
}
|
||||
|
||||
GpuObject::write_back_func_t StorageBufferGpuObject::GetWriteBackFunc() const
|
||||
{
|
||||
return write_back;
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
#include "Emulator/Graphics/Objects/StorageTexture.h"
|
||||
|
||||
#include "Kyty/Core/DbgAssert.h"
|
||||
#include "Kyty/Core/Vector.h"
|
||||
|
||||
#include "Emulator/Config.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 {
|
||||
|
||||
static VkFormat get_texture_format(uint32_t dfmt, uint32_t nfmt)
|
||||
{
|
||||
if (nfmt == 9 && dfmt == 10)
|
||||
{
|
||||
return VK_FORMAT_R8G8B8A8_SRGB;
|
||||
}
|
||||
if (nfmt == 0 && dfmt == 10)
|
||||
{
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
if (nfmt == 9 && dfmt == 37)
|
||||
{
|
||||
return VK_FORMAT_BC3_SRGB_BLOCK;
|
||||
}
|
||||
EXIT("unknown format: nfmt = %u, dfmt = %u\n", nfmt, dfmt);
|
||||
return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
|
||||
static VkComponentSwizzle get_swizzle(uint8_t s)
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case 0: return VK_COMPONENT_SWIZZLE_ZERO; break;
|
||||
case 1: return VK_COMPONENT_SWIZZLE_ONE; break;
|
||||
case 4: return VK_COMPONENT_SWIZZLE_R; break;
|
||||
case 5: return VK_COMPONENT_SWIZZLE_G; break;
|
||||
case 6: return VK_COMPONENT_SWIZZLE_B; break;
|
||||
case 7: return VK_COMPONENT_SWIZZLE_A; break;
|
||||
case 2:
|
||||
case 3:
|
||||
default: EXIT("unknown swizzle: %d\n", static_cast<int>(s));
|
||||
}
|
||||
return VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
}
|
||||
|
||||
static VkImageUsageFlags get_usage()
|
||||
{
|
||||
VkImageUsageFlags vk_usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
vk_usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
|
||||
return vk_usage;
|
||||
}
|
||||
|
||||
static bool CheckFormat(GraphicContext* ctx, VkImageCreateInfo* image_info)
|
||||
{
|
||||
VkImageFormatProperties props {};
|
||||
if (vkGetPhysicalDeviceImageFormatProperties(ctx->physical_device, image_info->format, image_info->imageType, image_info->tiling,
|
||||
image_info->usage, image_info->flags, &props) == VK_ERROR_FORMAT_NOT_SUPPORTED)
|
||||
{
|
||||
if (image_info->format == VK_FORMAT_R8G8B8A8_SRGB)
|
||||
{
|
||||
// TODO() convert SRGB -> LINEAR in shader
|
||||
image_info->format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
bool result = CheckFormat(ctx, image_info);
|
||||
printf("replace VK_FORMAT_R8G8B8A8_SRGB => VK_FORMAT_R8G8B8A8_UNORM [%s]\n", (!result ? "FAIL" : "SUCCESS"));
|
||||
return result;
|
||||
}
|
||||
if (image_info->format == VK_FORMAT_B8G8R8A8_SRGB)
|
||||
{
|
||||
// TODO() convert SRGB -> LINEAR in shader
|
||||
image_info->format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
bool result = CheckFormat(ctx, image_info);
|
||||
printf("replace VK_FORMAT_B8G8R8A8_SRGB => VK_FORMAT_B8G8R8A8_UNORM [%s]\n", (!result ? "FAIL" : "SUCCESS"));
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CheckSwizzle(GraphicContext* /*ctx*/, VkImageCreateInfo* image_info, VkComponentMapping* components)
|
||||
{
|
||||
if ((image_info->usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0)
|
||||
{
|
||||
if (components->r == VK_COMPONENT_SWIZZLE_R && components->g == VK_COMPONENT_SWIZZLE_G && components->b == VK_COMPONENT_SWIZZLE_B &&
|
||||
components->a == VK_COMPONENT_SWIZZLE_A)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (components->r == VK_COMPONENT_SWIZZLE_B && components->g == VK_COMPONENT_SWIZZLE_G && components->b == VK_COMPONENT_SWIZZLE_R &&
|
||||
components->a == VK_COMPONENT_SWIZZLE_A && image_info->format == VK_FORMAT_R8G8B8A8_SRGB)
|
||||
{
|
||||
printf("replace VK_FORMAT_R8G8B8A8_SRGB => VK_FORMAT_B8G8R8A8_SRGB\n");
|
||||
|
||||
components->r = VK_COMPONENT_SWIZZLE_R;
|
||||
components->g = VK_COMPONENT_SWIZZLE_G;
|
||||
components->b = VK_COMPONENT_SWIZZLE_B;
|
||||
components->a = VK_COMPONENT_SWIZZLE_A;
|
||||
image_info->format = VK_FORMAT_B8G8R8A8_SRGB;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO() swizzle channels in shader
|
||||
|
||||
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("StorageTextureObject::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<StorageTextureVulkanImage*>(obj);
|
||||
|
||||
auto tile = params[StorageTextureObject::PARAM_TILE];
|
||||
auto dfmt = params[StorageTextureObject::PARAM_DFMT_NFMT] >> 32u;
|
||||
auto nfmt = params[StorageTextureObject::PARAM_DFMT_NFMT] & 0xffffffffu;
|
||||
auto width = params[StorageTextureObject::PARAM_WIDTH_HEIGHT] >> 32u;
|
||||
auto height = params[StorageTextureObject::PARAM_WIDTH_HEIGHT] & 0xffffffffu;
|
||||
auto levels = params[StorageTextureObject::PARAM_LEVELS];
|
||||
auto pitch = params[StorageTextureObject::PARAM_PITCH];
|
||||
bool neo = Config::IsNeo();
|
||||
|
||||
VkImageLayout vk_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
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);
|
||||
|
||||
// dbg_test_mipmaps(ctx, VK_FORMAT_BC3_SRGB_BLOCK, 512, 512);
|
||||
|
||||
uint32_t offset = 0;
|
||||
uint32_t mip_width = width;
|
||||
uint32_t mip_height = height;
|
||||
uint32_t mip_pitch = pitch;
|
||||
|
||||
Vector<BufferImageCopy> regions(levels);
|
||||
for (uint32_t i = 0; i < levels; i++)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(level_sizes[i] == 0);
|
||||
|
||||
auto mipmap_offset = UtilCalcMipmapOffset(i, width, height);
|
||||
|
||||
regions[i].offset = offset;
|
||||
regions[i].width = mip_width;
|
||||
regions[i].height = mip_height;
|
||||
regions[i].pitch = mip_pitch;
|
||||
regions[i].dst_level = 0;
|
||||
regions[i].dst_x = mipmap_offset.first;
|
||||
regions[i].dst_y = mipmap_offset.second;
|
||||
|
||||
offset += level_sizes[i];
|
||||
|
||||
if (mip_width > 1)
|
||||
{
|
||||
mip_width /= 2;
|
||||
}
|
||||
if (mip_height > 1)
|
||||
{
|
||||
mip_height /= 2;
|
||||
}
|
||||
if (mip_pitch > 1)
|
||||
{
|
||||
mip_pitch /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
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 if (tile == 8)
|
||||
{
|
||||
UtilFillImage(ctx, vk_obj, reinterpret_cast<void*>(*vaddr), *size, regions, static_cast<uint64_t>(vk_layout));
|
||||
}
|
||||
}
|
||||
|
||||
static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("StorageTextureObject::Create");
|
||||
|
||||
EXIT_IF(size == nullptr || vaddr == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(params == nullptr);
|
||||
|
||||
auto dfmt = params[StorageTextureObject::PARAM_DFMT_NFMT] >> 32u;
|
||||
auto nfmt = params[StorageTextureObject::PARAM_DFMT_NFMT] & 0xffffffffu;
|
||||
auto width = params[StorageTextureObject::PARAM_WIDTH_HEIGHT] >> 32u;
|
||||
auto height = params[StorageTextureObject::PARAM_WIDTH_HEIGHT] & 0xffffffffu;
|
||||
auto levels = params[StorageTextureObject::PARAM_LEVELS];
|
||||
auto swizzle = params[StorageTextureObject::PARAM_SWIZZLE];
|
||||
|
||||
VkImageUsageFlags vk_usage = get_usage();
|
||||
|
||||
VkComponentMapping components {};
|
||||
|
||||
components.r = get_swizzle(swizzle & 0xffu);
|
||||
components.g = get_swizzle((swizzle >> 8u) & 0xffu);
|
||||
components.b = get_swizzle((swizzle >> 16u) & 0xffu);
|
||||
components.a = get_swizzle((swizzle >> 24u) & 0xffu);
|
||||
|
||||
auto pixel_format = get_texture_format(dfmt, nfmt);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(pixel_format == VK_FORMAT_UNDEFINED);
|
||||
EXIT_NOT_IMPLEMENTED(width == 0);
|
||||
EXIT_NOT_IMPLEMENTED(height == 0);
|
||||
|
||||
if (levels > 1)
|
||||
{
|
||||
height += (height > 1 ? height / 2 : 1);
|
||||
}
|
||||
|
||||
auto* vk_obj = new StorageTextureVulkanImage;
|
||||
|
||||
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 = width;
|
||||
image_info.extent.height = height;
|
||||
image_info.extent.depth = 1;
|
||||
image_info.mipLevels = 1;
|
||||
image_info.arrayLayers = 1;
|
||||
image_info.format = pixel_format;
|
||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
image_info.usage = vk_usage;
|
||||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
if (!CheckSwizzle(ctx, &image_info, &components))
|
||||
{
|
||||
EXIT("swizzle is not supported");
|
||||
}
|
||||
|
||||
if (!CheckFormat(ctx, &image_info))
|
||||
{
|
||||
EXIT("format is not supported");
|
||||
}
|
||||
|
||||
vk_obj->extent.width = width;
|
||||
vk_obj->extent.height = height;
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
update_func(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 = components;
|
||||
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 = VK_REMAINING_MIP_LEVELS;
|
||||
|
||||
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
|
||||
|
||||
return vk_obj;
|
||||
}
|
||||
|
||||
static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("StorageTextureObject::delete_func");
|
||||
|
||||
auto* vk_obj = reinterpret_cast<StorageTextureVulkanImage*>(obj);
|
||||
|
||||
EXIT_IF(vk_obj == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
DeleteDescriptor(vk_obj);
|
||||
|
||||
vkDestroyImageView(ctx->device, vk_obj->image_view, nullptr);
|
||||
|
||||
vkDestroyImage(ctx->device, vk_obj->image, nullptr);
|
||||
|
||||
VulkanFree(ctx, mem);
|
||||
|
||||
delete vk_obj;
|
||||
}
|
||||
|
||||
bool StorageTextureObject::Equal(const uint64_t* other) const
|
||||
{
|
||||
return (params[PARAM_DFMT_NFMT] == other[PARAM_DFMT_NFMT] && params[PARAM_PITCH] == other[PARAM_PITCH] &&
|
||||
params[PARAM_WIDTH_HEIGHT] == other[PARAM_WIDTH_HEIGHT] && params[PARAM_LEVELS] == other[PARAM_LEVELS] &&
|
||||
params[PARAM_TILE] == other[PARAM_TILE] && params[PARAM_NEO] == other[PARAM_NEO] &&
|
||||
params[PARAM_SWIZZLE] == other[PARAM_SWIZZLE]);
|
||||
}
|
||||
|
||||
GpuObject::create_func_t StorageTextureObject::GetCreateFunc() const
|
||||
{
|
||||
return create_func;
|
||||
}
|
||||
|
||||
GpuObject::delete_func_t StorageTextureObject::GetDeleteFunc() const
|
||||
{
|
||||
return delete_func;
|
||||
}
|
||||
|
||||
GpuObject::update_func_t StorageTextureObject::GetUpdateFunc() const
|
||||
{
|
||||
return update_func;
|
||||
}
|
||||
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
#endif
|
||||
@@ -22,6 +22,10 @@ static VkFormat get_texture_format(uint32_t dfmt, uint32_t nfmt)
|
||||
{
|
||||
return VK_FORMAT_R8G8B8A8_SRGB;
|
||||
}
|
||||
if (nfmt == 0 && dfmt == 10)
|
||||
{
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
if (nfmt == 9 && dfmt == 37)
|
||||
{
|
||||
return VK_FORMAT_BC3_SRGB_BLOCK;
|
||||
@@ -47,6 +51,15 @@ static VkComponentSwizzle get_swizzle(uint8_t s)
|
||||
return VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
}
|
||||
|
||||
static VkImageUsageFlags get_usage()
|
||||
{
|
||||
VkImageUsageFlags vk_usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
|
||||
vk_usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
|
||||
return vk_usage;
|
||||
}
|
||||
|
||||
static bool CheckFormat(GraphicContext* ctx, VkImageCreateInfo* image_info)
|
||||
{
|
||||
VkImageFormatProperties props {};
|
||||
@@ -104,30 +117,190 @@ static bool CheckSwizzle(GraphicContext* /*ctx*/, VkImageCreateInfo* image_info,
|
||||
return true;
|
||||
}
|
||||
|
||||
void* TextureObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const
|
||||
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("TextureObject::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<TextureVulkanImage*>(obj);
|
||||
|
||||
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;
|
||||
auto height = params[TextureObject::PARAM_WIDTH_HEIGHT] & 0xffffffffu;
|
||||
auto levels = params[TextureObject::PARAM_LEVELS];
|
||||
auto pitch = params[TextureObject::PARAM_PITCH];
|
||||
bool neo = Config::IsNeo();
|
||||
|
||||
VkImageLayout vk_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
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);
|
||||
|
||||
// dbg_test_mipmaps(ctx, VK_FORMAT_BC3_SRGB_BLOCK, 512, 512);
|
||||
|
||||
uint32_t offset = 0;
|
||||
uint32_t mip_width = width;
|
||||
uint32_t mip_height = height;
|
||||
uint32_t mip_pitch = pitch;
|
||||
|
||||
Vector<BufferImageCopy> regions(levels);
|
||||
for (uint32_t i = 0; i < levels; i++)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(level_sizes[i] == 0);
|
||||
|
||||
regions[i].offset = offset;
|
||||
regions[i].width = mip_width;
|
||||
regions[i].height = mip_height;
|
||||
regions[i].pitch = mip_pitch;
|
||||
regions[i].dst_level = i;
|
||||
regions[i].dst_x = 0;
|
||||
regions[i].dst_y = 0;
|
||||
|
||||
offset += level_sizes[i];
|
||||
|
||||
if (mip_width > 1)
|
||||
{
|
||||
mip_width /= 2;
|
||||
}
|
||||
if (mip_height > 1)
|
||||
{
|
||||
mip_height /= 2;
|
||||
}
|
||||
if (mip_pitch > 1)
|
||||
{
|
||||
mip_pitch /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
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 if (tile == 8)
|
||||
{
|
||||
UtilFillImage(ctx, vk_obj, reinterpret_cast<void*>(*vaddr), *size, regions, static_cast<uint64_t>(vk_layout));
|
||||
}
|
||||
}
|
||||
|
||||
static void update2_func(GraphicContext* ctx, const uint64_t* params, void* obj, const Vector<GpuMemoryObject>& objects)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("TextureObject::update2_func");
|
||||
|
||||
EXIT_IF(obj == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(params == nullptr);
|
||||
EXIT_IF(objects.IsEmpty());
|
||||
|
||||
auto* vk_obj = static_cast<TextureVulkanImage*>(obj);
|
||||
|
||||
auto width = params[TextureObject::PARAM_WIDTH_HEIGHT] >> 32u;
|
||||
auto height = params[TextureObject::PARAM_WIDTH_HEIGHT] & 0xffffffffu;
|
||||
auto levels = params[TextureObject::PARAM_LEVELS];
|
||||
|
||||
VkImageLayout vk_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(levels >= 16);
|
||||
|
||||
uint32_t mip_width = width;
|
||||
uint32_t mip_height = height;
|
||||
|
||||
Vector<ImageImageCopy> regions(levels);
|
||||
|
||||
if (objects.Size() == 1 && objects.At(0).type == GpuMemoryObjectType::StorageTexture)
|
||||
{
|
||||
auto* src_obj = static_cast<TextureVulkanImage*>(objects.At(0).obj);
|
||||
|
||||
for (uint32_t i = 0; i < levels; i++)
|
||||
{
|
||||
auto mipmap_offset = UtilCalcMipmapOffset(i, width, height);
|
||||
|
||||
regions[i].src_image = src_obj;
|
||||
regions[i].src_level = 0;
|
||||
regions[i].dst_level = i;
|
||||
regions[i].width = mip_width;
|
||||
regions[i].height = mip_height;
|
||||
regions[i].src_x = mipmap_offset.first;
|
||||
regions[i].src_y = mipmap_offset.second;
|
||||
regions[i].dst_x = 0;
|
||||
regions[i].dst_y = 0;
|
||||
|
||||
if (mip_width > 1)
|
||||
{
|
||||
mip_width /= 2;
|
||||
}
|
||||
if (mip_height > 1)
|
||||
{
|
||||
mip_height /= 2;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(levels != objects.Size());
|
||||
|
||||
for (uint32_t i = 0; i < levels; i++)
|
||||
{
|
||||
const auto& object = objects.At(i);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(object.type != GpuMemoryObjectType::RenderTexture);
|
||||
|
||||
auto* src_obj = static_cast<RenderTextureVulkanImage*>(object.obj);
|
||||
|
||||
regions[i].src_image = src_obj;
|
||||
regions[i].src_level = 0;
|
||||
regions[i].dst_level = i;
|
||||
regions[i].width = mip_width;
|
||||
regions[i].height = mip_height;
|
||||
regions[i].src_x = 0;
|
||||
regions[i].src_y = 0;
|
||||
regions[i].dst_x = 0;
|
||||
regions[i].dst_y = 0;
|
||||
|
||||
if (mip_width > 1)
|
||||
{
|
||||
mip_width /= 2;
|
||||
}
|
||||
if (mip_height > 1)
|
||||
{
|
||||
mip_height /= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UtilFillImage(ctx, regions, vk_obj, static_cast<uint64_t>(vk_layout));
|
||||
}
|
||||
|
||||
static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("TextureObject::Create");
|
||||
|
||||
EXIT_IF(size == nullptr || vaddr == nullptr);
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(params == nullptr);
|
||||
|
||||
auto dfmt = params[PARAM_DFMT_NFMT] >> 32u;
|
||||
auto nfmt = params[PARAM_DFMT_NFMT] & 0xffffffffu;
|
||||
auto width = params[PARAM_WIDTH_HEIGHT] >> 32u;
|
||||
auto height = params[PARAM_WIDTH_HEIGHT] & 0xffffffffu;
|
||||
auto levels = params[PARAM_LEVELS];
|
||||
auto swizzle = params[PARAM_SWIZZLE];
|
||||
auto usage = params[PARAM_USAGE];
|
||||
auto dfmt = params[TextureObject::PARAM_DFMT_NFMT] >> 32u;
|
||||
auto nfmt = params[TextureObject::PARAM_DFMT_NFMT] & 0xffffffffu;
|
||||
auto width = params[TextureObject::PARAM_WIDTH_HEIGHT] >> 32u;
|
||||
auto height = params[TextureObject::PARAM_WIDTH_HEIGHT] & 0xffffffffu;
|
||||
auto levels = params[TextureObject::PARAM_LEVELS];
|
||||
auto swizzle = params[TextureObject::PARAM_SWIZZLE];
|
||||
|
||||
VkImageUsageFlags vk_usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
|
||||
switch (usage)
|
||||
{
|
||||
case TEXTURE_USAGE_SAMPLED: vk_usage |= VK_IMAGE_USAGE_SAMPLED_BIT; break;
|
||||
case TEXTURE_USAGE_STORAGE: vk_usage |= VK_IMAGE_USAGE_STORAGE_BIT; break;
|
||||
default: EXIT("unknown usage: %u\n", static_cast<uint32_t>(usage));
|
||||
}
|
||||
VkImageUsageFlags vk_usage = get_usage();
|
||||
|
||||
VkComponentMapping components {};
|
||||
|
||||
@@ -194,7 +367,7 @@ void* TextureObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const ui
|
||||
|
||||
vk_obj->memory = *mem;
|
||||
|
||||
GetUpdateFunc()(ctx, params, vk_obj, vaddr, size, vaddr_num);
|
||||
update_func(ctx, params, vk_obj, vaddr, size, vaddr_num);
|
||||
|
||||
VkImageViewCreateInfo create_info {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
@@ -208,7 +381,7 @@ void* TextureObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const ui
|
||||
create_info.subresourceRange.baseArrayLayer = 0;
|
||||
create_info.subresourceRange.baseMipLevel = 0;
|
||||
create_info.subresourceRange.layerCount = 1;
|
||||
create_info.subresourceRange.levelCount = 1;
|
||||
create_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
|
||||
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view);
|
||||
|
||||
@@ -217,96 +390,110 @@ void* TextureObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const ui
|
||||
return vk_obj;
|
||||
}
|
||||
|
||||
static void update_func(GraphicContext* ctx, const uint64_t* params, void* obj, const uint64_t* vaddr, const uint64_t* size, int vaddr_num)
|
||||
static void* create2_func(GraphicContext* ctx, const uint64_t* params, const Vector<GpuMemoryObject>& objects, VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("TextureObject::update_func");
|
||||
KYTY_PROFILER_BLOCK("TextureObject::CreateFromObjects");
|
||||
|
||||
EXIT_IF(obj == nullptr);
|
||||
EXIT_IF(objects.IsEmpty());
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(params == nullptr);
|
||||
EXIT_IF(vaddr == nullptr || size == nullptr || vaddr_num != 1);
|
||||
|
||||
auto* vk_obj = static_cast<TextureVulkanImage*>(obj);
|
||||
auto dfmt = params[TextureObject::PARAM_DFMT_NFMT] >> 32u;
|
||||
auto nfmt = params[TextureObject::PARAM_DFMT_NFMT] & 0xffffffffu;
|
||||
auto width = params[TextureObject::PARAM_WIDTH_HEIGHT] >> 32u;
|
||||
auto height = params[TextureObject::PARAM_WIDTH_HEIGHT] & 0xffffffffu;
|
||||
auto levels = params[TextureObject::PARAM_LEVELS];
|
||||
auto swizzle = params[TextureObject::PARAM_SWIZZLE];
|
||||
|
||||
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;
|
||||
auto height = params[TextureObject::PARAM_WIDTH_HEIGHT] & 0xffffffffu;
|
||||
auto levels = params[TextureObject::PARAM_LEVELS];
|
||||
auto pitch = params[TextureObject::PARAM_PITCH];
|
||||
auto usage = params[TextureObject::PARAM_USAGE];
|
||||
bool neo = Config::IsNeo();
|
||||
VkImageUsageFlags vk_usage = get_usage();
|
||||
|
||||
VkImageLayout vk_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkComponentMapping components {};
|
||||
|
||||
switch (usage)
|
||||
components.r = get_swizzle(swizzle & 0xffu);
|
||||
components.g = get_swizzle((swizzle >> 8u) & 0xffu);
|
||||
components.b = get_swizzle((swizzle >> 16u) & 0xffu);
|
||||
components.a = get_swizzle((swizzle >> 24u) & 0xffu);
|
||||
|
||||
auto pixel_format = get_texture_format(dfmt, nfmt);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(pixel_format == VK_FORMAT_UNDEFINED);
|
||||
EXIT_NOT_IMPLEMENTED(width == 0);
|
||||
EXIT_NOT_IMPLEMENTED(height == 0);
|
||||
|
||||
auto* vk_obj = new TextureVulkanImage;
|
||||
|
||||
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 = width;
|
||||
image_info.extent.height = height;
|
||||
image_info.extent.depth = 1;
|
||||
image_info.mipLevels = levels;
|
||||
image_info.arrayLayers = 1;
|
||||
image_info.format = pixel_format;
|
||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
image_info.usage = vk_usage;
|
||||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
if (!CheckSwizzle(ctx, &image_info, &components))
|
||||
{
|
||||
case TextureObject::TEXTURE_USAGE_SAMPLED: vk_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; break;
|
||||
case TextureObject::TEXTURE_USAGE_STORAGE: vk_layout = VK_IMAGE_LAYOUT_GENERAL; break;
|
||||
default: EXIT("unknown usage: %u\n", static_cast<uint32_t>(usage));
|
||||
EXIT("swizzle is not supported");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// dbg_test_mipmaps(ctx, VK_FORMAT_BC3_SRGB_BLOCK, 512, 512);
|
||||
|
||||
uint32_t offset = 0;
|
||||
uint32_t mip_width = width;
|
||||
uint32_t mip_height = height;
|
||||
uint32_t mip_pitch = pitch;
|
||||
|
||||
Vector<BufferImageCopy> regions(levels);
|
||||
for (uint32_t i = 0; i < levels; i++)
|
||||
if (!CheckFormat(ctx, &image_info))
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(level_sizes[i] == 0);
|
||||
|
||||
regions[i].offset = offset;
|
||||
regions[i].width = mip_width;
|
||||
regions[i].height = mip_height;
|
||||
regions[i].pitch = mip_pitch;
|
||||
|
||||
offset += level_sizes[i];
|
||||
|
||||
if (mip_width > 1)
|
||||
{
|
||||
mip_width /= 2;
|
||||
}
|
||||
if (mip_height > 1)
|
||||
{
|
||||
mip_height /= 2;
|
||||
}
|
||||
if (mip_pitch > 1)
|
||||
{
|
||||
mip_pitch /= 2;
|
||||
}
|
||||
EXIT("format is not supported");
|
||||
}
|
||||
|
||||
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 if (tile == 8)
|
||||
{
|
||||
UtilFillImage(ctx, vk_obj, reinterpret_cast<void*>(*vaddr), *size, regions, static_cast<uint64_t>(vk_layout));
|
||||
}
|
||||
}
|
||||
vk_obj->extent.width = width;
|
||||
vk_obj->extent.height = height;
|
||||
vk_obj->format = image_info.format;
|
||||
vk_obj->image = nullptr;
|
||||
vk_obj->image_view = nullptr;
|
||||
vk_obj->layout = image_info.initialLayout;
|
||||
|
||||
bool TextureObject::Equal(const uint64_t* other) const
|
||||
{
|
||||
return (params[PARAM_DFMT_NFMT] == other[PARAM_DFMT_NFMT] && params[PARAM_PITCH] == other[PARAM_PITCH] &&
|
||||
params[PARAM_WIDTH_HEIGHT] == other[PARAM_WIDTH_HEIGHT] && params[PARAM_USAGE] == other[PARAM_USAGE] &&
|
||||
params[PARAM_LEVELS] == other[PARAM_LEVELS] && params[PARAM_TILE] == other[PARAM_TILE] &&
|
||||
params[PARAM_NEO] == other[PARAM_NEO] && params[PARAM_SWIZZLE] == other[PARAM_SWIZZLE]);
|
||||
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;
|
||||
|
||||
update2_func(ctx, params, vk_obj, objects);
|
||||
|
||||
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 = components;
|
||||
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 = VK_REMAINING_MIP_LEVELS;
|
||||
|
||||
vkCreateImageView(ctx->device, &create_info, nullptr, &vk_obj->image_view);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(vk_obj->image_view == nullptr);
|
||||
|
||||
return vk_obj;
|
||||
}
|
||||
|
||||
static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
|
||||
@@ -329,6 +516,24 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
|
||||
delete vk_obj;
|
||||
}
|
||||
|
||||
bool TextureObject::Equal(const uint64_t* other) const
|
||||
{
|
||||
return (params[PARAM_DFMT_NFMT] == other[PARAM_DFMT_NFMT] && params[PARAM_PITCH] == other[PARAM_PITCH] &&
|
||||
params[PARAM_WIDTH_HEIGHT] == other[PARAM_WIDTH_HEIGHT] && params[PARAM_LEVELS] == other[PARAM_LEVELS] &&
|
||||
params[PARAM_TILE] == other[PARAM_TILE] && params[PARAM_NEO] == other[PARAM_NEO] &&
|
||||
params[PARAM_SWIZZLE] == other[PARAM_SWIZZLE]);
|
||||
}
|
||||
|
||||
GpuObject::create_func_t TextureObject::GetCreateFunc() const
|
||||
{
|
||||
return create_func;
|
||||
}
|
||||
|
||||
GpuObject::create_from_objects_func_t TextureObject::GetCreateFromObjectsFunc() const
|
||||
{
|
||||
return create2_func;
|
||||
}
|
||||
|
||||
GpuObject::delete_func_t TextureObject::GetDeleteFunc() const
|
||||
{
|
||||
return delete_func;
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
void* VertexBufferGpuObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem) const
|
||||
static void* create_func(GraphicContext* ctx, const uint64_t* /*params*/, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("VertexBufferGpuObject::Create");
|
||||
|
||||
@@ -59,11 +59,6 @@ static void update_func(GraphicContext* /*ctx*/, const uint64_t* /*params*/, voi
|
||||
KYTY_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
bool VertexBufferGpuObject::Equal(const uint64_t* /*other*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* /*mem*/)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("VertexBufferGpuObject::delete_func");
|
||||
@@ -79,6 +74,16 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* /*mem*/)
|
||||
delete vk_obj;
|
||||
}
|
||||
|
||||
bool VertexBufferGpuObject::Equal(const uint64_t* /*other*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
GpuObject::create_func_t VertexBufferGpuObject::GetCreateFunc() const
|
||||
{
|
||||
return create_func;
|
||||
}
|
||||
|
||||
GpuObject::delete_func_t VertexBufferGpuObject::GetDeleteFunc() const
|
||||
{
|
||||
return delete_func;
|
||||
|
||||
@@ -14,7 +14,58 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
void* VideoOutBufferObject::Create(GraphicContext* ctx, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) const
|
||||
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("VideoOutBufferObject::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<VideoOutVulkanImage*>(obj);
|
||||
|
||||
bool tiled = (params[VideoOutBufferObject::PARAM_TILED] != 0);
|
||||
bool neo = (params[VideoOutBufferObject::PARAM_NEO] != 0);
|
||||
auto pitch = params[VideoOutBufferObject::PARAM_PITCH];
|
||||
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);
|
||||
auto* temp_buf = new uint8_t[*size];
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint64_t* vaddr, const uint64_t* size, int vaddr_num,
|
||||
VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("VideoOutBufferObject::Create");
|
||||
|
||||
@@ -22,9 +73,9 @@ void* VideoOutBufferObject::Create(GraphicContext* ctx, const uint64_t* vaddr, c
|
||||
EXIT_IF(mem == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
auto pixel_format = params[PARAM_FORMAT];
|
||||
auto width = params[PARAM_WIDTH];
|
||||
auto height = params[PARAM_HEIGHT];
|
||||
auto pixel_format = params[VideoOutBufferObject::PARAM_FORMAT];
|
||||
auto width = params[VideoOutBufferObject::PARAM_WIDTH];
|
||||
auto height = params[VideoOutBufferObject::PARAM_HEIGHT];
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(pixel_format != 0x80000000);
|
||||
EXIT_NOT_IMPLEMENTED(width == 0);
|
||||
@@ -81,7 +132,7 @@ void* VideoOutBufferObject::Create(GraphicContext* ctx, const uint64_t* vaddr, c
|
||||
|
||||
// EXIT_NOT_IMPLEMENTED(mem->requirements.size > *size);
|
||||
|
||||
GetUpdateFunc()(ctx, params, vk_obj, vaddr, size, vaddr_num);
|
||||
update_func(ctx, params, vk_obj, vaddr, size, vaddr_num);
|
||||
|
||||
VkImageViewCreateInfo create_info {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
@@ -107,63 +158,6 @@ void* VideoOutBufferObject::Create(GraphicContext* ctx, const uint64_t* vaddr, c
|
||||
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("VideoOutBufferObject::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<VideoOutVulkanImage*>(obj);
|
||||
|
||||
bool tiled = (params[VideoOutBufferObject::PARAM_TILED] != 0);
|
||||
bool neo = (params[VideoOutBufferObject::PARAM_NEO] != 0);
|
||||
auto pitch = params[VideoOutBufferObject::PARAM_PITCH];
|
||||
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);
|
||||
auto* temp_buf = new uint8_t[*size];
|
||||
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 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_NEO] == other[PARAM_NEO]);
|
||||
}
|
||||
|
||||
static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
|
||||
{
|
||||
KYTY_PROFILER_BLOCK("VideoOutBufferObject::delete_func");
|
||||
@@ -187,6 +181,18 @@ static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* mem)
|
||||
delete vk_obj;
|
||||
}
|
||||
|
||||
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_NEO] == other[PARAM_NEO]);
|
||||
}
|
||||
|
||||
GpuObject::create_func_t VideoOutBufferObject::GetCreateFunc() const
|
||||
{
|
||||
return create_func;
|
||||
}
|
||||
|
||||
GpuObject::delete_func_t VideoOutBufferObject::GetDeleteFunc() const
|
||||
{
|
||||
return delete_func;
|
||||
|
||||
@@ -215,6 +215,7 @@ static String dbg_fmt_to_str(const ShaderInstruction& inst)
|
||||
case ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7: return U"Vdata4Vaddr3StSsDmask7"; break;
|
||||
case ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF: return U"Vdata4Vaddr3StSsDmaskF"; break;
|
||||
case ShaderInstructionFormat::Vdata4Vaddr3StDmaskF: return U"Vdata4Vaddr3StDmaskF"; break;
|
||||
case ShaderInstructionFormat::Vdata4Vaddr4StDmaskF: return U"Vdata4Vaddr4StDmaskF"; break;
|
||||
case ShaderInstructionFormat::SVdstSVsrc0SVsrc1: return U"SVdstSVsrc0SVsrc1"; break;
|
||||
case ShaderInstructionFormat::VdstVsrc0Vsrc1Smask2: return U"VdstVsrc0Vsrc1Smask2"; break;
|
||||
case ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2: return U"VdstVsrc0Vsrc1Vsrc2"; break;
|
||||
@@ -1554,6 +1555,17 @@ KYTY_SHADER_PARSER(shader_parse_mimg)
|
||||
inst.dst.size = 4;
|
||||
}
|
||||
break;
|
||||
case 0x09:
|
||||
inst.type = ShaderInstructionType::ImageStoreMip;
|
||||
inst.src[0].size = 4;
|
||||
inst.src[1].size = 8;
|
||||
inst.src_num = 2;
|
||||
if (dmask == 0xf)
|
||||
{
|
||||
inst.format = ShaderInstructionFormat::Vdata4Vaddr4StDmaskF;
|
||||
inst.dst.size = 4;
|
||||
}
|
||||
break;
|
||||
case 0x20:
|
||||
inst.type = ShaderInstructionType::ImageSample;
|
||||
inst.src[0].size = 3;
|
||||
@@ -1572,6 +1584,12 @@ KYTY_SHADER_PARSER(shader_parse_mimg)
|
||||
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown mimg opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
|
||||
}
|
||||
|
||||
if (inst.format == ShaderInstructionFormat::Unknown)
|
||||
{
|
||||
printf("%s", dst->DbgDump().C_Str());
|
||||
EXIT("unknown mimg format for opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc)
|
||||
}
|
||||
|
||||
dst->GetInstructions().Add(inst);
|
||||
|
||||
return size;
|
||||
@@ -1857,10 +1875,10 @@ static void ps_check(const PsStageRegisters& ps)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(ps.target_output_mode[0] != 4 && ps.target_output_mode[0] != 9);
|
||||
EXIT_NOT_IMPLEMENTED(ps.conservative_z_export_value != 0x00000000);
|
||||
EXIT_NOT_IMPLEMENTED(ps.shader_z_behavior != 0x00000001);
|
||||
EXIT_NOT_IMPLEMENTED(ps.shader_z_behavior != 0x00000001 && ps.shader_z_behavior != 0x00000000);
|
||||
// EXIT_NOT_IMPLEMENTED(ps.shader_kill_enable != false);
|
||||
EXIT_NOT_IMPLEMENTED(ps.shader_z_export_enable != false);
|
||||
EXIT_NOT_IMPLEMENTED(ps.shader_execute_on_noop != false);
|
||||
// EXIT_NOT_IMPLEMENTED(ps.shader_execute_on_noop != false);
|
||||
// EXIT_NOT_IMPLEMENTED(ps.m_spiShaderPgmRsrc1Ps != 0x002c0000);
|
||||
// EXIT_NOT_IMPLEMENTED(ps.m_spiShaderPgmRsrc2Ps != 0x00000000);
|
||||
// EXIT_NOT_IMPLEMENTED(ps.vgprs != 0x00 && ps.vgprs != 0x01);
|
||||
@@ -2199,8 +2217,8 @@ static void ShaderGetStorageBuffer(ShaderStorageResources* info, int start_index
|
||||
info->buffers_num++;
|
||||
}
|
||||
|
||||
static void ShaderGetTextureBuffer(ShaderTextureResources* info, int start_index, int slot, const UserSgprInfo& user_sgpr,
|
||||
const uint32_t* extended_buffer)
|
||||
static void ShaderGetTextureBuffer(ShaderTextureResources* info, int start_index, int slot, ShaderTextureUsage usage,
|
||||
const UserSgprInfo& user_sgpr, const uint32_t* extended_buffer)
|
||||
{
|
||||
EXIT_IF(info == nullptr);
|
||||
|
||||
@@ -2216,6 +2234,7 @@ static void ShaderGetTextureBuffer(ShaderTextureResources* info, int start_index
|
||||
info->start_register[index] = start_index;
|
||||
info->extended[index] = extended;
|
||||
info->slots[index] = slot;
|
||||
info->usages[index] = usage;
|
||||
|
||||
if (!extended)
|
||||
{
|
||||
@@ -2302,7 +2321,7 @@ static void ShaderGetGdsPointer(ShaderGdsResources* info, int start_index, int s
|
||||
info->pointers_num++;
|
||||
}
|
||||
|
||||
static void ShaderCalcBindingIndices(ShaderBindResources* bind)
|
||||
void ShaderCalcBindingIndices(ShaderBindResources* bind)
|
||||
{
|
||||
int binding_index = 0;
|
||||
|
||||
@@ -2310,30 +2329,28 @@ static void ShaderCalcBindingIndices(ShaderBindResources* bind)
|
||||
|
||||
if (bind->storage_buffers.buffers_num > 0)
|
||||
{
|
||||
bind->storage_buffers.binding_index = binding_index;
|
||||
bind->storage_buffers.binding_index = binding_index++;
|
||||
bind->push_constant_size += bind->storage_buffers.buffers_num * 16;
|
||||
binding_index++;
|
||||
}
|
||||
|
||||
if (bind->textures2D.textures_num > 0)
|
||||
{
|
||||
bind->textures2D.binding_index = binding_index;
|
||||
bind->textures2D.binding_sampled_index = binding_index++;
|
||||
bind->textures2D.binding_storage_index = binding_index++;
|
||||
|
||||
bind->push_constant_size += bind->textures2D.textures_num * 32;
|
||||
binding_index++;
|
||||
}
|
||||
|
||||
if (bind->samplers.samplers_num > 0)
|
||||
{
|
||||
bind->samplers.binding_index = binding_index;
|
||||
bind->samplers.binding_index = binding_index++;
|
||||
bind->push_constant_size += bind->samplers.samplers_num * 16;
|
||||
binding_index++;
|
||||
}
|
||||
|
||||
if (bind->gds_pointers.pointers_num > 0)
|
||||
{
|
||||
bind->gds_pointers.binding_index = binding_index;
|
||||
bind->gds_pointers.binding_index = binding_index++;
|
||||
bind->push_constant_size += (((bind->gds_pointers.pointers_num - 1) / 4) + 1) * 16;
|
||||
binding_index++;
|
||||
}
|
||||
|
||||
EXIT_IF((bind->push_constant_size % 16) != 0);
|
||||
@@ -2411,6 +2428,7 @@ void ShaderGetInputInfoVS(const VertexShaderInfo* regs, ShaderVertexInputInfo* i
|
||||
ShaderCalcBindingIndices(&info->bind);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputInfo* vs_info, ShaderPixelInputInfo* ps_info)
|
||||
{
|
||||
EXIT_IF(vs_info == nullptr);
|
||||
@@ -2420,6 +2438,8 @@ void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputIn
|
||||
ps_info->input_num = regs->ps_regs.ps_in_control;
|
||||
ps_info->ps_pos_xy = (regs->ps_regs.ps_input_ena == 0x00000302 && regs->ps_regs.ps_input_addr == 0x00000302);
|
||||
ps_info->ps_pixel_kill_enable = regs->ps_regs.shader_kill_enable;
|
||||
ps_info->ps_early_z = (regs->ps_regs.shader_z_behavior == 1);
|
||||
ps_info->ps_execute_on_noop = regs->ps_regs.shader_execute_on_noop;
|
||||
|
||||
for (uint32_t i = 0; i < ps_info->input_num; i++)
|
||||
{
|
||||
@@ -2454,8 +2474,8 @@ void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputIn
|
||||
regs->ps_user_sgpr, extended_buffer);
|
||||
} else if (usage.flags == 3)
|
||||
{
|
||||
ShaderGetTextureBuffer(&ps_info->bind.textures2D, usage.start_register, usage.slot, regs->ps_user_sgpr,
|
||||
extended_buffer);
|
||||
ShaderGetTextureBuffer(&ps_info->bind.textures2D, usage.start_register, usage.slot, ShaderTextureUsage::ReadOnly,
|
||||
regs->ps_user_sgpr, extended_buffer);
|
||||
EXIT_NOT_IMPLEMENTED(ps_info->bind.textures2D.textures[ps_info->bind.textures2D.textures_num - 1].Type() != 9);
|
||||
}
|
||||
break;
|
||||
@@ -2468,6 +2488,15 @@ void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputIn
|
||||
ShaderGetStorageBuffer(&ps_info->bind.storage_buffers, usage.start_register, usage.slot, ShaderStorageUsage::Constant,
|
||||
regs->ps_user_sgpr, extended_buffer);
|
||||
break;
|
||||
case 0x04:
|
||||
EXIT_NOT_IMPLEMENTED(usage.flags != 3);
|
||||
if (usage.flags == 3)
|
||||
{
|
||||
ShaderGetTextureBuffer(&ps_info->bind.textures2D, usage.start_register, usage.slot, ShaderTextureUsage::ReadWrite,
|
||||
regs->ps_user_sgpr, extended_buffer);
|
||||
EXIT_NOT_IMPLEMENTED(ps_info->bind.textures2D.textures[ps_info->bind.textures2D.textures_num - 1].Type() != 9);
|
||||
}
|
||||
break;
|
||||
case 0x1b:
|
||||
EXIT_NOT_IMPLEMENTED(usage.flags != 0);
|
||||
EXIT_NOT_IMPLEMENTED(usage.slot != 1);
|
||||
@@ -2524,7 +2553,8 @@ void ShaderGetInputInfoCS(const ComputeShaderInfo* regs, ShaderComputeInputInfo*
|
||||
regs->cs_user_sgpr, extended_buffer);
|
||||
} else if (usage.flags == 3)
|
||||
{
|
||||
ShaderGetTextureBuffer(&info->bind.textures2D, usage.start_register, usage.slot, regs->cs_user_sgpr, extended_buffer);
|
||||
ShaderGetTextureBuffer(&info->bind.textures2D, usage.start_register, usage.slot, ShaderTextureUsage::ReadOnly,
|
||||
regs->cs_user_sgpr, extended_buffer);
|
||||
EXIT_NOT_IMPLEMENTED(info->bind.textures2D.textures[info->bind.textures2D.textures_num - 1].Type() != 9);
|
||||
}
|
||||
break;
|
||||
@@ -2562,21 +2592,22 @@ void ShaderGetInputInfoCS(const ComputeShaderInfo* regs, ShaderComputeInputInfo*
|
||||
|
||||
static void ShaderDbgDumpResources(const ShaderBindResources& bind)
|
||||
{
|
||||
printf("\t descriptor_set_slot = %u\n", bind.descriptor_set_slot);
|
||||
printf("\t push_constant_offset = %u\n", bind.push_constant_offset);
|
||||
printf("\t push_constant_size = %u\n", bind.push_constant_size);
|
||||
printf("\t storage_buffers.buffers_num = %d\n", bind.storage_buffers.buffers_num);
|
||||
printf("\t storage_buffers.binding_index = %d\n", bind.storage_buffers.binding_index);
|
||||
printf("\t textures.textures_num = %d\n", bind.textures2D.textures_num);
|
||||
printf("\t textures.binding_index = %d\n", bind.textures2D.binding_index);
|
||||
printf("\t samplers.samplers_num = %d\n", bind.samplers.samplers_num);
|
||||
printf("\t samplers.binding_index = %d\n", bind.samplers.binding_index);
|
||||
printf("\t gds_pointers.pointers_num = %d\n", bind.gds_pointers.pointers_num);
|
||||
printf("\t gds_pointers.binding_index = %d\n", bind.gds_pointers.binding_index);
|
||||
printf("\t extended.used = %s\n", (bind.extended.used ? "true" : "false"));
|
||||
printf("\t extended.slot = %d\n", bind.extended.slot);
|
||||
printf("\t extended.start_register = %d\n", bind.extended.start_register);
|
||||
printf("\t extended.data.Base = %" PRIx64 "\n", bind.extended.data.Base());
|
||||
printf("\t descriptor_set_slot = %u\n", bind.descriptor_set_slot);
|
||||
printf("\t push_constant_offset = %u\n", bind.push_constant_offset);
|
||||
printf("\t push_constant_size = %u\n", bind.push_constant_size);
|
||||
printf("\t storage_buffers.buffers_num = %d\n", bind.storage_buffers.buffers_num);
|
||||
printf("\t storage_buffers.binding_index = %d\n", bind.storage_buffers.binding_index);
|
||||
printf("\t textures.textures_num = %d\n", bind.textures2D.textures_num);
|
||||
printf("\t textures.binding_sampled_index = %d\n", bind.textures2D.binding_sampled_index);
|
||||
printf("\t textures.binding_storage_index = %d\n", bind.textures2D.binding_storage_index);
|
||||
printf("\t samplers.samplers_num = %d\n", bind.samplers.samplers_num);
|
||||
printf("\t samplers.binding_index = %d\n", bind.samplers.binding_index);
|
||||
printf("\t gds_pointers.pointers_num = %d\n", bind.gds_pointers.pointers_num);
|
||||
printf("\t gds_pointers.binding_index = %d\n", bind.gds_pointers.binding_index);
|
||||
printf("\t extended.used = %s\n", (bind.extended.used ? "true" : "false"));
|
||||
printf("\t extended.slot = %d\n", bind.extended.slot);
|
||||
printf("\t extended.start_register = %d\n", bind.extended.start_register);
|
||||
printf("\t extended.data.Base = %" PRIx64 "\n", bind.extended.data.Base());
|
||||
|
||||
for (int i = 0; i < bind.storage_buffers.buffers_num; i++)
|
||||
{
|
||||
@@ -2640,6 +2671,7 @@ static void ShaderDbgDumpResources(const ShaderBindResources& bind)
|
||||
printf("\t\t slot = %d\n", bind.textures2D.slots[i]);
|
||||
printf("\t\t start_register = %d\n", bind.textures2D.start_register[i]);
|
||||
printf("\t\t extended = %s\n", (bind.textures2D.extended[i] ? "true" : "false"));
|
||||
printf("\t\t usage = %s\n", Core::EnumName(bind.textures2D.usages[i]).C_Str());
|
||||
}
|
||||
|
||||
for (int i = 0; i < bind.samplers.samplers_num; i++)
|
||||
@@ -2754,6 +2786,8 @@ void ShaderDbgDumpInputInfo(const ShaderPixelInputInfo* info)
|
||||
printf("\t input_num = %u\n", info->input_num);
|
||||
printf("\t ps_pos_xy = %s\n", info->ps_pos_xy ? "true" : "false");
|
||||
printf("\t ps_pixel_kill_enable = %s\n", info->ps_pixel_kill_enable ? "true" : "false");
|
||||
printf("\t ps_early_z = %s\n", info->ps_early_z ? "true" : "false");
|
||||
printf("\t ps_execute_on_noop = %s\n", info->ps_execute_on_noop ? "true" : "false");
|
||||
|
||||
for (uint32_t i = 0; i < info->input_num; i++)
|
||||
{
|
||||
@@ -3140,17 +3174,92 @@ Vector<uint32_t> ShaderRecompileCS(const ShaderCode& code, const ShaderComputeIn
|
||||
return ret;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
static ShaderBindParameters ShaderUpdateBindInfo(const ShaderCode& code, const ShaderBindResources* bind)
|
||||
{
|
||||
ShaderBindParameters p {};
|
||||
|
||||
auto find_image_op = [&](int index, int s, bool& found, bool& without_sampler)
|
||||
{
|
||||
const auto& insts = code.GetInstructions();
|
||||
int size = static_cast<int>(insts.Size());
|
||||
for (int i = index; i < size; i++)
|
||||
{
|
||||
const auto& inst = insts.At(i);
|
||||
|
||||
if ((inst.dst.type == ShaderOperandType::Sgpr && s >= inst.dst.register_id && s < inst.dst.register_id + inst.dst.size) ||
|
||||
(inst.dst2.type == ShaderOperandType::Sgpr && s >= inst.dst2.register_id && s < inst.dst2.register_id + inst.dst2.size) ||
|
||||
inst.type == ShaderInstructionType::SEndpgm)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (inst.type == ShaderInstructionType::ImageStoreMip || inst.type == ShaderInstructionType::ImageLoad)
|
||||
{
|
||||
if (inst.src[1].register_id == s)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(found && !without_sampler);
|
||||
without_sampler = true;
|
||||
found = true;
|
||||
}
|
||||
} else if (inst.type == ShaderInstructionType::ImageSample)
|
||||
{
|
||||
if (inst.src[1].register_id == s)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(found && without_sampler);
|
||||
without_sampler = false;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (bind->textures2D.textures_num > 0)
|
||||
{
|
||||
bool image_sample = code.HasAnyOf({ShaderInstructionType::ImageSample});
|
||||
bool image_load = code.HasAnyOf({ShaderInstructionType::ImageLoad});
|
||||
const auto& insts = code.GetInstructions();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(image_sample && image_load);
|
||||
for (int ti = 0; ti < bind->textures2D.textures_num; ti++)
|
||||
{
|
||||
bool found = false;
|
||||
if (bind->textures2D.extended[ti])
|
||||
{
|
||||
int s = bind->extended.start_register;
|
||||
|
||||
p.textures2D_without_sampler = image_load;
|
||||
int index = 0;
|
||||
for (const auto& inst: insts)
|
||||
{
|
||||
if ((inst.dst.type == ShaderOperandType::Sgpr && s >= inst.dst.register_id &&
|
||||
s < inst.dst.register_id + inst.dst.size) ||
|
||||
(inst.dst2.type == ShaderOperandType::Sgpr && s >= inst.dst2.register_id &&
|
||||
s < inst.dst2.register_id + inst.dst2.size) ||
|
||||
inst.type == ShaderInstructionType::SEndpgm)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (inst.type == ShaderInstructionType::SLoadDwordx8 && inst.src[0].register_id == s &&
|
||||
static_cast<int>(inst.src[1].constant.u >> 2u) + 16 == bind->textures2D.start_register[ti])
|
||||
{
|
||||
find_image_op(index + 1, inst.dst.register_id, found, p.textures2d_without_sampler[ti]);
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
} else
|
||||
{
|
||||
find_image_op(0, bind->textures2D.start_register[ti], found, p.textures2d_without_sampler[ti]);
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(!found);
|
||||
|
||||
if (p.textures2d_without_sampler[ti])
|
||||
{
|
||||
p.textures2d_storage_num++;
|
||||
} else
|
||||
{
|
||||
p.textures2d_sampled_num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@@ -3176,16 +3285,16 @@ static void ShaderGetBindIds(ShaderId* ret, const ShaderBindResources& bind)
|
||||
|
||||
for (int i = 0; i < bind.storage_buffers.buffers_num; i++)
|
||||
{
|
||||
const auto& r = bind.storage_buffers.buffers[i];
|
||||
// const auto& r = bind.storage_buffers.buffers[i];
|
||||
|
||||
ret->ids.Add(static_cast<uint32_t>(r.SwizzleEnabled()));
|
||||
ret->ids.Add(r.DstSelX());
|
||||
ret->ids.Add(r.DstSelY());
|
||||
ret->ids.Add(r.DstSelZ());
|
||||
ret->ids.Add(r.DstSelW());
|
||||
ret->ids.Add(r.Nfmt());
|
||||
ret->ids.Add(r.Dfmt());
|
||||
ret->ids.Add(static_cast<uint32_t>(r.AddTid()));
|
||||
// ret->ids.Add(static_cast<uint32_t>(r.SwizzleEnabled()));
|
||||
// ret->ids.Add(r.DstSelX());
|
||||
// ret->ids.Add(r.DstSelY());
|
||||
// ret->ids.Add(r.DstSelZ());
|
||||
// ret->ids.Add(r.DstSelW());
|
||||
// ret->ids.Add(r.Nfmt());
|
||||
// ret->ids.Add(r.Dfmt());
|
||||
// ret->ids.Add(static_cast<uint32_t>(r.AddTid()));
|
||||
ret->ids.Add(bind.storage_buffers.slots[i]);
|
||||
ret->ids.Add(bind.storage_buffers.start_register[i]);
|
||||
ret->ids.Add(static_cast<uint32_t>(bind.storage_buffers.extended[i]));
|
||||
@@ -3196,66 +3305,67 @@ static void ShaderGetBindIds(ShaderId* ret, const ShaderBindResources& bind)
|
||||
|
||||
for (int i = 0; i < bind.textures2D.textures_num; i++)
|
||||
{
|
||||
const auto& r = bind.textures2D.textures[i];
|
||||
ret->ids.Add(r.MinLod());
|
||||
ret->ids.Add(r.Dfmt());
|
||||
ret->ids.Add(r.Nfmt());
|
||||
ret->ids.Add(r.Width());
|
||||
ret->ids.Add(r.Height());
|
||||
ret->ids.Add(r.PerfMod());
|
||||
ret->ids.Add(static_cast<uint32_t>(r.Interlaced()));
|
||||
ret->ids.Add(r.DstSelX());
|
||||
ret->ids.Add(r.DstSelY());
|
||||
ret->ids.Add(r.DstSelZ());
|
||||
ret->ids.Add(r.DstSelW());
|
||||
ret->ids.Add(r.BaseLevel());
|
||||
ret->ids.Add(r.LastLevel());
|
||||
ret->ids.Add(r.TilingIdx());
|
||||
ret->ids.Add(static_cast<uint32_t>(r.Pow2Pad()));
|
||||
ret->ids.Add(r.Type());
|
||||
ret->ids.Add(r.Depth());
|
||||
ret->ids.Add(r.Pitch());
|
||||
ret->ids.Add(r.BaseArray());
|
||||
ret->ids.Add(r.LastArray());
|
||||
ret->ids.Add(r.MinLodWarn());
|
||||
ret->ids.Add(r.CounterBankId());
|
||||
ret->ids.Add(static_cast<uint32_t>(r.LodHdwCntEn()));
|
||||
// const auto& r = bind.textures2D.textures[i];
|
||||
// ret->ids.Add(r.MinLod());
|
||||
// ret->ids.Add(r.Dfmt());
|
||||
// ret->ids.Add(r.Nfmt());
|
||||
// ret->ids.Add(r.Width());
|
||||
// ret->ids.Add(r.Height());
|
||||
// ret->ids.Add(r.PerfMod());
|
||||
// ret->ids.Add(static_cast<uint32_t>(r.Interlaced()));
|
||||
// ret->ids.Add(r.DstSelX());
|
||||
// ret->ids.Add(r.DstSelY());
|
||||
// ret->ids.Add(r.DstSelZ());
|
||||
// ret->ids.Add(r.DstSelW());
|
||||
// ret->ids.Add(r.BaseLevel());
|
||||
// ret->ids.Add(r.LastLevel());
|
||||
// ret->ids.Add(r.TilingIdx());
|
||||
// ret->ids.Add(static_cast<uint32_t>(r.Pow2Pad()));
|
||||
// ret->ids.Add(r.Type());
|
||||
// ret->ids.Add(r.Depth());
|
||||
// ret->ids.Add(r.Pitch());
|
||||
// ret->ids.Add(r.BaseArray());
|
||||
// ret->ids.Add(r.LastArray());
|
||||
// ret->ids.Add(r.MinLodWarn());
|
||||
// ret->ids.Add(r.CounterBankId());
|
||||
// ret->ids.Add(static_cast<uint32_t>(r.LodHdwCntEn()));
|
||||
ret->ids.Add(bind.textures2D.slots[i]);
|
||||
ret->ids.Add(bind.textures2D.start_register[i]);
|
||||
ret->ids.Add(static_cast<uint32_t>(bind.textures2D.extended[i]));
|
||||
ret->ids.Add(static_cast<uint32_t>(bind.textures2D.usages[i]));
|
||||
}
|
||||
|
||||
ret->ids.Add(bind.samplers.samplers_num);
|
||||
|
||||
for (int i = 0; i < bind.samplers.samplers_num; i++)
|
||||
{
|
||||
const auto& r = bind.samplers.samplers[i];
|
||||
// const auto& r = bind.samplers.samplers[i];
|
||||
|
||||
ret->ids.Add(r.ClampX());
|
||||
ret->ids.Add(r.ClampY());
|
||||
ret->ids.Add(r.ClampZ());
|
||||
ret->ids.Add(r.MaxAnisoRatio());
|
||||
ret->ids.Add(r.DepthCompareFunc());
|
||||
ret->ids.Add(static_cast<uint32_t>(r.ForceUnormCoords()));
|
||||
ret->ids.Add(r.AnisoThreshold());
|
||||
ret->ids.Add(static_cast<uint32_t>(r.McCoordTrunc()));
|
||||
ret->ids.Add(static_cast<uint32_t>(r.ForceDegamma()));
|
||||
ret->ids.Add(r.AnisoBias());
|
||||
ret->ids.Add(static_cast<uint32_t>(r.TruncCoord()));
|
||||
ret->ids.Add(static_cast<uint32_t>(r.DisableCubeWrap()));
|
||||
ret->ids.Add(r.FilterMode());
|
||||
ret->ids.Add(r.MinLod());
|
||||
ret->ids.Add(r.MaxLod());
|
||||
ret->ids.Add(r.PerfMip());
|
||||
ret->ids.Add(r.PerfZ());
|
||||
ret->ids.Add(r.LodBias());
|
||||
ret->ids.Add(r.LodBiasSec());
|
||||
ret->ids.Add(r.XyMagFilter());
|
||||
ret->ids.Add(r.XyMinFilter());
|
||||
ret->ids.Add(r.ZFilter());
|
||||
ret->ids.Add(r.MipFilter());
|
||||
ret->ids.Add(r.BorderColorPtr());
|
||||
ret->ids.Add(r.BorderColorType());
|
||||
// ret->ids.Add(r.ClampX());
|
||||
// ret->ids.Add(r.ClampY());
|
||||
// ret->ids.Add(r.ClampZ());
|
||||
// ret->ids.Add(r.MaxAnisoRatio());
|
||||
// ret->ids.Add(r.DepthCompareFunc());
|
||||
// ret->ids.Add(static_cast<uint32_t>(r.ForceUnormCoords()));
|
||||
// ret->ids.Add(r.AnisoThreshold());
|
||||
// ret->ids.Add(static_cast<uint32_t>(r.McCoordTrunc()));
|
||||
// ret->ids.Add(static_cast<uint32_t>(r.ForceDegamma()));
|
||||
// ret->ids.Add(r.AnisoBias());
|
||||
// ret->ids.Add(static_cast<uint32_t>(r.TruncCoord()));
|
||||
// ret->ids.Add(static_cast<uint32_t>(r.DisableCubeWrap()));
|
||||
// ret->ids.Add(r.FilterMode());
|
||||
// ret->ids.Add(r.MinLod());
|
||||
// ret->ids.Add(r.MaxLod());
|
||||
// ret->ids.Add(r.PerfMip());
|
||||
// ret->ids.Add(r.PerfZ());
|
||||
// ret->ids.Add(r.LodBias());
|
||||
// ret->ids.Add(r.LodBiasSec());
|
||||
// ret->ids.Add(r.XyMagFilter());
|
||||
// ret->ids.Add(r.XyMinFilter());
|
||||
// ret->ids.Add(r.ZFilter());
|
||||
// ret->ids.Add(r.MipFilter());
|
||||
// ret->ids.Add(r.BorderColorPtr());
|
||||
// ret->ids.Add(r.BorderColorType());
|
||||
ret->ids.Add(bind.samplers.slots[i]);
|
||||
ret->ids.Add(bind.samplers.start_register[i]);
|
||||
ret->ids.Add(static_cast<uint32_t>(bind.samplers.extended[i]));
|
||||
@@ -3360,6 +3470,8 @@ ShaderId ShaderGetIdPS(const PixelShaderInfo* regs, const ShaderPixelInputInfo*
|
||||
ret.ids.Add(input_info->input_num);
|
||||
ret.ids.Add(static_cast<uint32_t>(input_info->ps_pos_xy));
|
||||
ret.ids.Add(static_cast<uint32_t>(input_info->ps_pixel_kill_enable));
|
||||
ret.ids.Add(static_cast<uint32_t>(input_info->ps_early_z));
|
||||
ret.ids.Add(static_cast<uint32_t>(input_info->ps_execute_on_noop));
|
||||
|
||||
for (uint32_t i = 0; i < input_info->input_num; i++)
|
||||
{
|
||||
|
||||
@@ -183,6 +183,85 @@ constexpr char32_t FUNC_ADDC[] = UR"(
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
constexpr char32_t FUNC_MIPMAP[] = UR"(
|
||||
; uvec2 mipmap(uint lod, uint width, uint height)
|
||||
; {
|
||||
; uint mip_width = width;
|
||||
; uint mip_height = height;
|
||||
; uint mip_x = 0;
|
||||
; uint mip_y = 0;
|
||||
; for (uint i = 0; i < 16; i++)
|
||||
; {
|
||||
; if (i == lod)
|
||||
; {
|
||||
; return uvec2(mip_x, mip_y);
|
||||
; }
|
||||
; bool odd = ((i & 1u) != 0u);
|
||||
; mip_x += (odd ? mip_width : 0u);
|
||||
; mip_y += (odd ? 0u : mip_height);
|
||||
; mip_width >>= (mip_width > 1u ? 1u : 0u);
|
||||
; mip_height >>= (mip_height > 1u ? 1u : 0u);
|
||||
; }
|
||||
; return uvec2(mip_x, mip_y);
|
||||
; }
|
||||
%mipmap = OpFunction %v2uint None %function_u2_u_u_u
|
||||
%mipmap_33 = OpFunctionParameter %uint
|
||||
%mipmap_16 = OpFunctionParameter %uint
|
||||
%mipmap_18 = OpFunctionParameter %uint
|
||||
%mipmap_14 = OpLabel
|
||||
OpSelectionMerge %mipmap_188 None
|
||||
OpSwitch %uint_0 %mipmap_191
|
||||
%mipmap_191 = OpLabel
|
||||
OpBranch %mipmap_23
|
||||
%mipmap_23 = OpLabel
|
||||
%mipmap_296 = OpPhi %uint %uint_0 %mipmap_191 %mipmap_56 %mipmap_26
|
||||
%mipmap_295 = OpPhi %uint %mipmap_18 %mipmap_191 %mipmap_66 %mipmap_26
|
||||
%mipmap_294 = OpPhi %uint %uint_0 %mipmap_191 %mipmap_51 %mipmap_26
|
||||
%mipmap_293 = OpPhi %uint %mipmap_16 %mipmap_191 %mipmap_61 %mipmap_26
|
||||
%mipmap_292 = OpPhi %uint %uint_0 %mipmap_191 %mipmap_70 %mipmap_26
|
||||
OpLoopMerge %mipmap_25 %mipmap_26 None
|
||||
OpBranch %mipmap_27
|
||||
%mipmap_27 = OpLabel
|
||||
%mipmap_31 = OpULessThan %bool %mipmap_292 %uint_16
|
||||
OpBranchConditional %mipmap_31 %mipmap_24 %mipmap_25
|
||||
%mipmap_24 = OpLabel
|
||||
%mipmap_34 = OpIEqual %bool %mipmap_292 %mipmap_33
|
||||
OpSelectionMerge %mipmap_36 None
|
||||
OpBranchConditional %mipmap_34 %mipmap_35 %mipmap_36
|
||||
%mipmap_35 = OpLabel
|
||||
%mipmap_39 = OpCompositeConstruct %v2uint %mipmap_294 %mipmap_296
|
||||
OpBranch %mipmap_25
|
||||
%mipmap_36 = OpLabel
|
||||
%mipmap_45 = OpBitwiseAnd %uint %mipmap_292 %uint_1
|
||||
%mipmap_46 = OpINotEqual %bool %mipmap_45 %uint_0
|
||||
%mipmap_49 = OpSelect %uint %mipmap_46 %mipmap_293 %uint_0
|
||||
%mipmap_51 = OpIAdd %uint %mipmap_294 %mipmap_49
|
||||
%mipmap_54 = OpSelect %uint %mipmap_46 %uint_0 %mipmap_295
|
||||
%mipmap_56 = OpIAdd %uint %mipmap_296 %mipmap_54
|
||||
%mipmap_58 = OpUGreaterThan %bool %mipmap_293 %uint_1
|
||||
%mipmap_59 = OpSelect %uint %mipmap_58 %uint_1 %uint_0
|
||||
%mipmap_61 = OpShiftRightLogical %uint %mipmap_293 %mipmap_59
|
||||
%mipmap_63 = OpUGreaterThan %bool %mipmap_295 %uint_1
|
||||
%mipmap_64 = OpSelect %uint %mipmap_63 %uint_1 %uint_0
|
||||
%mipmap_66 = OpShiftRightLogical %uint %mipmap_295 %mipmap_64
|
||||
OpBranch %mipmap_26
|
||||
%mipmap_26 = OpLabel
|
||||
%mipmap_70 = OpIAdd %uint %mipmap_292 %int_1
|
||||
OpBranch %mipmap_23
|
||||
%mipmap_25 = OpLabel
|
||||
%mipmap_302 = OpPhi %v2uint %undef_v2uint %mipmap_27 %mipmap_39 %mipmap_35
|
||||
%mipmap_297 = OpPhi %bool %false %mipmap_27 %true %mipmap_35
|
||||
OpSelectionMerge %mipmap_195 None
|
||||
OpBranchConditional %mipmap_297 %mipmap_188 %mipmap_195
|
||||
%mipmap_195 = OpLabel
|
||||
%mipmap_73 = OpCompositeConstruct %v2uint %mipmap_294 %mipmap_296
|
||||
OpBranch %mipmap_188
|
||||
%mipmap_188 = OpLabel
|
||||
%mipmap_301 = OpPhi %v2uint %mipmap_302 %mipmap_25 %mipmap_73 %mipmap_195
|
||||
OpReturnValue %mipmap_301
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
constexpr char32_t FUNC_ORDERED[] = UR"(
|
||||
; bool unordered(float f1, float f2)
|
||||
; {
|
||||
@@ -1140,7 +1219,8 @@ public:
|
||||
void SetPsInputInfo(const ShaderPixelInputInfo* input_info) { m_ps_input_info = input_info; }
|
||||
[[nodiscard]] const ShaderPixelInputInfo* GetPsInputInfo() const { return m_ps_input_info; }
|
||||
|
||||
[[nodiscard]] const ShaderBindResources* GetBindInfo() const { return m_bind; }
|
||||
[[nodiscard]] const ShaderBindResources* GetBindInfo() const { return m_bind; }
|
||||
[[nodiscard]] const ShaderBindParameters& GetBindParams() const { return m_bind_params; }
|
||||
|
||||
void AddConstantUint(uint32_t u);
|
||||
void AddConstantInt(int i);
|
||||
@@ -2103,10 +2183,11 @@ KYTY_RECOMPILER_FUNC(Recompile_Exp_Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done)
|
||||
|
||||
KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata3Vaddr3StSsDmask7)
|
||||
{
|
||||
const auto& inst = code.GetInstructions().At(index);
|
||||
const auto* bind_info = spirv->GetBindInfo();
|
||||
const auto& inst = code.GetInstructions().At(index);
|
||||
const auto* bind_info = spirv->GetBindInfo();
|
||||
const auto& bind_params = spirv->GetBindParams();
|
||||
|
||||
if (bind_info != nullptr && bind_info->textures2D.textures_num > 0 && bind_info->samplers.samplers_num > 0)
|
||||
if (bind_info != nullptr && bind_params.textures2d_sampled_num > 0 && bind_info->samplers.samplers_num > 0)
|
||||
{
|
||||
auto dst_value0 = operand_variable_to_str(inst.dst, 0);
|
||||
auto dst_value1 = operand_variable_to_str(inst.dst, 1);
|
||||
@@ -2127,8 +2208,8 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata3Vaddr3StSsDmask7)
|
||||
|
||||
static const char32_t* text = UR"(
|
||||
%t24_<index> = OpLoad %uint %<src1_value0>
|
||||
%t26_<index> = OpAccessChain %_ptr_UniformConstant_Image %textures2D %t24_<index>
|
||||
%t27_<index> = OpLoad %Image %t26_<index>
|
||||
%t26_<index> = OpAccessChain %_ptr_UniformConstant_ImageS %textures2D_S %t24_<index>
|
||||
%t27_<index> = OpLoad %ImageS %t26_<index>
|
||||
%t33_<index> = OpLoad %uint %<src2_value0>
|
||||
%t35_<index> = OpAccessChain %_ptr_UniformConstant_Sampler %samplers %t33_<index>
|
||||
%t36_<index> = OpLoad %Sampler %t35_<index>
|
||||
@@ -2167,10 +2248,11 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata3Vaddr3StSsDmask7)
|
||||
|
||||
KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF)
|
||||
{
|
||||
const auto& inst = code.GetInstructions().At(index);
|
||||
const auto* bind_info = spirv->GetBindInfo();
|
||||
const auto& inst = code.GetInstructions().At(index);
|
||||
const auto* bind_info = spirv->GetBindInfo();
|
||||
const auto& bind_params = spirv->GetBindParams();
|
||||
|
||||
if (bind_info != nullptr && bind_info->textures2D.textures_num > 0 && bind_info->samplers.samplers_num > 0)
|
||||
if (bind_info != nullptr && bind_params.textures2d_sampled_num > 0 && bind_info->samplers.samplers_num > 0)
|
||||
{
|
||||
auto dst_value0 = operand_variable_to_str(inst.dst, 0);
|
||||
auto dst_value1 = operand_variable_to_str(inst.dst, 1);
|
||||
@@ -2192,8 +2274,8 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF)
|
||||
|
||||
static const char32_t* text = UR"(
|
||||
%t24_<index> = OpLoad %uint %<src1_value0>
|
||||
%t26_<index> = OpAccessChain %_ptr_UniformConstant_Image %textures2D %t24_<index>
|
||||
%t27_<index> = OpLoad %Image %t26_<index>
|
||||
%t26_<index> = OpAccessChain %_ptr_UniformConstant_ImageS %textures2D_S %t24_<index>
|
||||
%t27_<index> = OpLoad %ImageS %t26_<index>
|
||||
%t33_<index> = OpLoad %uint %<src2_value0>
|
||||
%t35_<index> = OpAccessChain %_ptr_UniformConstant_Sampler %samplers %t33_<index>
|
||||
%t36_<index> = OpLoad %Sampler %t35_<index>
|
||||
@@ -2236,10 +2318,11 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF)
|
||||
|
||||
KYTY_RECOMPILER_FUNC(Recompile_ImageLoad_Vdata4Vaddr3StDmaskF)
|
||||
{
|
||||
const auto& inst = code.GetInstructions().At(index);
|
||||
const auto* bind_info = spirv->GetBindInfo();
|
||||
const auto& inst = code.GetInstructions().At(index);
|
||||
const auto* bind_info = spirv->GetBindInfo();
|
||||
const auto& bind_params = spirv->GetBindParams();
|
||||
|
||||
if (bind_info != nullptr && bind_info->textures2D.textures_num > 0)
|
||||
if (bind_info != nullptr && bind_params.textures2d_storage_num > 0)
|
||||
{
|
||||
auto dst_value0 = operand_variable_to_str(inst.dst, 0);
|
||||
auto dst_value1 = operand_variable_to_str(inst.dst, 1);
|
||||
@@ -2261,8 +2344,8 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageLoad_Vdata4Vaddr3StDmaskF)
|
||||
|
||||
static const char32_t* text = UR"(
|
||||
%t24_<index> = OpLoad %uint %<src1_value0>
|
||||
%t26_<index> = OpAccessChain %_ptr_UniformConstant_Image %textures2D %t24_<index>
|
||||
%t27_<index> = OpLoad %Image %t26_<index>
|
||||
%t26_<index> = OpAccessChain %_ptr_UniformConstant_ImageL %textures2D_L %t24_<index>
|
||||
%t27_<index> = OpLoad %ImageL %t26_<index>
|
||||
%t67_<index> = OpLoad %float %<src0_value0>
|
||||
%t69_<index> = OpBitcast %uint %t67_<index>
|
||||
%t70_<index> = OpLoad %float %<src0_value1>
|
||||
@@ -2300,6 +2383,80 @@ KYTY_RECOMPILER_FUNC(Recompile_ImageLoad_Vdata4Vaddr3StDmaskF)
|
||||
return false;
|
||||
}
|
||||
|
||||
KYTY_RECOMPILER_FUNC(Recompile_ImageStoreMip_Vdata4Vaddr4StDmaskF)
|
||||
{
|
||||
const auto& inst = code.GetInstructions().At(index);
|
||||
const auto* bind_info = spirv->GetBindInfo();
|
||||
const auto& bind_params = spirv->GetBindParams();
|
||||
|
||||
if (bind_info != nullptr && bind_params.textures2d_storage_num > 0)
|
||||
{
|
||||
auto dst_value0 = operand_variable_to_str(inst.dst, 0);
|
||||
auto dst_value1 = operand_variable_to_str(inst.dst, 1);
|
||||
auto dst_value2 = operand_variable_to_str(inst.dst, 2);
|
||||
auto dst_value3 = operand_variable_to_str(inst.dst, 3);
|
||||
|
||||
auto src0_value0 = operand_variable_to_str(inst.src[0], 0);
|
||||
auto src0_value1 = operand_variable_to_str(inst.src[0], 1);
|
||||
auto src0_value2 = operand_variable_to_str(inst.src[0], 2);
|
||||
|
||||
auto src1_value0 = operand_variable_to_str(inst.src[1], 0);
|
||||
auto src1_value2 = operand_variable_to_str(inst.src[1], 2);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(dst_value0.type != SpirvType::Float);
|
||||
EXIT_NOT_IMPLEMENTED(src0_value0.type != SpirvType::Float);
|
||||
EXIT_NOT_IMPLEMENTED(src1_value0.type != SpirvType::Uint);
|
||||
|
||||
// TODO() check VSKIP
|
||||
// TODO() check LOD_CLAMPED
|
||||
// TODO() swizzle channels
|
||||
// TODO() convert SRGB -> LINEAR if SRGB format was replaced with UNORM
|
||||
|
||||
static const char32_t* text = UR"(
|
||||
%t24_<index> = OpLoad %uint %<src1_value0>
|
||||
%t25_<index> = OpLoad %uint %<src1_value2>
|
||||
%t143_<index> = OpShiftRightLogical %uint %t25_<index> %uint_0
|
||||
%t145_<index> = OpBitwiseAnd %uint %t143_<index> %uint_0x00003fff
|
||||
%t146_<index> = OpIAdd %uint %t145_<index> %uint_1
|
||||
%t149_<index> = OpShiftRightLogical %uint %t25_<index> %uint_14
|
||||
%t150_<index> = OpBitwiseAnd %uint %t149_<index> %uint_0x00003fff
|
||||
%t151_<index> = OpIAdd %uint %t150_<index> %uint_1
|
||||
%t26_<index> = OpAccessChain %_ptr_UniformConstant_ImageL %textures2D_L %t24_<index>
|
||||
%t27_<index> = OpLoad %ImageL %t26_<index>
|
||||
%t67_<index> = OpLoad %float %<src0_value0>
|
||||
%t69_<index> = OpBitcast %uint %t67_<index>
|
||||
%t70_<index> = OpLoad %float %<src0_value1>
|
||||
%t71_<index> = OpBitcast %uint %t70_<index>
|
||||
%t701_<index> = OpLoad %float %<src0_value2>
|
||||
%t711_<index> = OpBitcast %uint %t701_<index>
|
||||
%t160_<index> = OpFunctionCall %v2uint %mipmap %t711_<index> %t146_<index> %t151_<index>
|
||||
%t73_<index> = OpCompositeConstruct %v2uint %t69_<index> %t71_<index>
|
||||
%t84_<index> = OpLoad %float %<dst_value0>
|
||||
%t85_<index> = OpLoad %float %<dst_value1>
|
||||
%t86_<index> = OpLoad %float %<dst_value2>
|
||||
%t87_<index> = OpLoad %float %<dst_value3>
|
||||
%t172_<index> = OpIAdd %v2uint %t160_<index> %t73_<index>
|
||||
%t88_<index> = OpCompositeConstruct %v4float %t84_<index> %t85_<index> %t86_<index> %t87_<index>
|
||||
OpImageWrite %t27_<index> %t172_<index> %t88_<index>
|
||||
)";
|
||||
*dst_source += String(text)
|
||||
.ReplaceStr(U"<index>", String::FromPrintf("%u", index))
|
||||
.ReplaceStr(U"<src0_value0>", src0_value0.value)
|
||||
.ReplaceStr(U"<src0_value1>", src0_value1.value)
|
||||
.ReplaceStr(U"<src0_value2>", src0_value2.value)
|
||||
.ReplaceStr(U"<src1_value0>", src1_value0.value)
|
||||
.ReplaceStr(U"<src1_value2>", src1_value2.value)
|
||||
.ReplaceStr(U"<dst_value0>", dst_value0.value)
|
||||
.ReplaceStr(U"<dst_value1>", dst_value1.value)
|
||||
.ReplaceStr(U"<dst_value2>", dst_value2.value)
|
||||
.ReplaceStr(U"<dst_value3>", dst_value3.value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* XXX: Andn2, Or, Nor, Cselect */
|
||||
KYTY_RECOMPILER_FUNC(Recompile_S_XXX_B64_Sdst2Ssrc02Ssrc12)
|
||||
{
|
||||
@@ -4533,6 +4690,7 @@ static RecompilerFunc g_recomp_func[] = {
|
||||
{Recompile_ImageLoad_Vdata4Vaddr3StDmaskF, ShaderInstructionType::ImageLoad, ShaderInstructionFormat::Vdata4Vaddr3StDmaskF, {U""}},
|
||||
{Recompile_ImageSample_Vdata3Vaddr3StSsDmask7, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7, {U""}},
|
||||
{Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF, {U""}},
|
||||
{Recompile_ImageStoreMip_Vdata4Vaddr4StDmaskF, ShaderInstructionType::ImageStoreMip, ShaderInstructionFormat::Vdata4Vaddr4StDmaskF, {U""}},
|
||||
|
||||
{Recompile_SBufferLoadDword_SdstSvSoffset, ShaderInstructionType::SBufferLoadDword, ShaderInstructionFormat::SdstSvSoffset, {U""}},
|
||||
{Recompile_SBufferLoadDwordx2_Sdst2SvSoffset, ShaderInstructionType::SBufferLoadDwordx2, ShaderInstructionFormat::Sdst2SvSoffset, {U""}},
|
||||
@@ -4954,15 +5112,15 @@ void Spirv::WriteHeader()
|
||||
<Imports>
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint <Type> %main "main" <Variables>
|
||||
<ExecutionMode>
|
||||
<ExecutionModes>
|
||||
)";
|
||||
|
||||
String header_str;
|
||||
String execution_mode;
|
||||
|
||||
Core::StringList vars;
|
||||
Core::StringList extensions;
|
||||
Core::StringList imports;
|
||||
Core::StringList execution_modes;
|
||||
|
||||
imports.Add(U"%GLSL_std_450 = OpExtInstImport \"GLSL.std.450\"");
|
||||
|
||||
@@ -4978,9 +5136,13 @@ void Spirv::WriteHeader()
|
||||
{
|
||||
vars.Add(U"%buf");
|
||||
}
|
||||
if (m_bind->textures2D.textures_num > 0)
|
||||
if (m_bind_params.textures2d_sampled_num > 0)
|
||||
{
|
||||
vars.Add(U"%textures2D");
|
||||
vars.Add(U"%textures2D_S");
|
||||
}
|
||||
if (m_bind_params.textures2d_storage_num > 0)
|
||||
{
|
||||
vars.Add(U"%textures2D_L");
|
||||
}
|
||||
if (m_bind->samplers.samplers_num > 0)
|
||||
{
|
||||
@@ -5010,9 +5172,13 @@ void Spirv::WriteHeader()
|
||||
{
|
||||
vars.Add(U"%gl_FragCoord");
|
||||
}
|
||||
if (m_ps_input_info->ps_early_z)
|
||||
{
|
||||
execution_modes.Add(U"OpExecutionMode %main EarlyFragmentTests\n");
|
||||
}
|
||||
}
|
||||
header_str = String(header).ReplaceStr(U"<Type>", U"Fragment");
|
||||
execution_mode = U"OpExecutionMode %main OriginUpperLeft\n";
|
||||
header_str = String(header).ReplaceStr(U"<Type>", U"Fragment");
|
||||
execution_modes.Add(U"OpExecutionMode %main OriginUpperLeft\n");
|
||||
// TODO() do we need PixelCenterInteger mode?
|
||||
break;
|
||||
case ShaderType::Vertex:
|
||||
@@ -5035,8 +5201,8 @@ void Spirv::WriteHeader()
|
||||
case ShaderType::Compute:
|
||||
if (m_cs_input_info != nullptr)
|
||||
{
|
||||
execution_mode = String::FromPrintf("OpExecutionMode %%main LocalSize %u %u %u", m_cs_input_info->threads_num[0],
|
||||
m_cs_input_info->threads_num[1], m_cs_input_info->threads_num[2]);
|
||||
execution_modes.Add(String::FromPrintf("OpExecutionMode %%main LocalSize %u %u %u", m_cs_input_info->threads_num[0],
|
||||
m_cs_input_info->threads_num[1], m_cs_input_info->threads_num[2]));
|
||||
}
|
||||
vars.Add(U"%gl_LocalInvocationID");
|
||||
vars.Add(U"%gl_WorkGroupID");
|
||||
@@ -5046,7 +5212,7 @@ void Spirv::WriteHeader()
|
||||
}
|
||||
|
||||
m_source += header_str.ReplaceStr(U"<Variables>", vars.Concat(U' '))
|
||||
.ReplaceStr(U"<ExecutionMode>", execution_mode)
|
||||
.ReplaceStr(U"<ExecutionModes>", execution_modes.Concat(U"\n" + String(U' ', 15)))
|
||||
.ReplaceStr(U"<Imports>", imports.Concat(U"\n" + String(U' ', 15)))
|
||||
.ReplaceStr(U"<Extensions>", extensions.Concat(U"\n" + String(U' ', 15)));
|
||||
}
|
||||
@@ -5136,9 +5302,14 @@ void Spirv::WriteAnnotations()
|
||||
OpDecorate %buf Binding <BindingIndex>
|
||||
)";
|
||||
|
||||
static const char32_t* textures_annotations = UR"(
|
||||
OpDecorate %textures2D DescriptorSet <DescriptorSet>
|
||||
OpDecorate %textures2D Binding <BindingIndex>
|
||||
static const char32_t* textures_annotations_s = UR"(
|
||||
OpDecorate %textures2D_S DescriptorSet <DescriptorSet>
|
||||
OpDecorate %textures2D_S Binding <BindingIndex>
|
||||
)";
|
||||
|
||||
static const char32_t* textures_annotations_l = UR"(
|
||||
OpDecorate %textures2D_L DescriptorSet <DescriptorSet>
|
||||
OpDecorate %textures2D_L Binding <BindingIndex>
|
||||
)";
|
||||
|
||||
static const char32_t* samplers_annotations = UR"(
|
||||
@@ -5169,11 +5340,17 @@ void Spirv::WriteAnnotations()
|
||||
.ReplaceStr(U"<DescriptorSet>", String::FromPrintf("%u", m_bind->descriptor_set_slot))
|
||||
.ReplaceStr(U"<BindingIndex>", String::FromPrintf("%d", m_bind->storage_buffers.binding_index));
|
||||
}
|
||||
if (m_bind->textures2D.textures_num > 0)
|
||||
if (m_bind_params.textures2d_sampled_num > 0)
|
||||
{
|
||||
m_source += String(textures_annotations)
|
||||
m_source += String(textures_annotations_s)
|
||||
.ReplaceStr(U"<DescriptorSet>", String::FromPrintf("%u", m_bind->descriptor_set_slot))
|
||||
.ReplaceStr(U"<BindingIndex>", String::FromPrintf("%d", m_bind->textures2D.binding_index));
|
||||
.ReplaceStr(U"<BindingIndex>", String::FromPrintf("%d", m_bind->textures2D.binding_sampled_index));
|
||||
}
|
||||
if (m_bind_params.textures2d_storage_num > 0)
|
||||
{
|
||||
m_source += String(textures_annotations_l)
|
||||
.ReplaceStr(U"<DescriptorSet>", String::FromPrintf("%u", m_bind->descriptor_set_slot))
|
||||
.ReplaceStr(U"<BindingIndex>", String::FromPrintf("%d", m_bind->textures2D.binding_storage_index));
|
||||
}
|
||||
if (m_bind->samplers.samplers_num > 0)
|
||||
{
|
||||
@@ -5210,6 +5387,8 @@ void Spirv::WriteTypes()
|
||||
%v4float = OpTypeVector %float 4
|
||||
%v2uint = OpTypeVector %uint 2
|
||||
%v3uint = OpTypeVector %uint 3
|
||||
%v4uint = OpTypeVector %uint 4
|
||||
%undef_v2uint = OpUndef %v2uint
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%_ptr_Input_uint = OpTypePointer Input %uint
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
@@ -5286,20 +5465,20 @@ void Spirv::WriteTypes()
|
||||
)";
|
||||
|
||||
static const char32_t* textures_sampled_types = UR"(
|
||||
%Image = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%textures2D_uint_<buffers_num> = OpConstant %uint <buffers_num>
|
||||
%_arr_Image_uint_<buffers_num> = OpTypeArray %Image %textures2D_uint_<buffers_num>
|
||||
%_ptr_UniformConstant__arr_Image_uint_<buffers_num> = OpTypePointer UniformConstant %_arr_Image_uint_<buffers_num>
|
||||
%_ptr_UniformConstant_Image = OpTypePointer UniformConstant %Image
|
||||
%SampledImage = OpTypeSampledImage %Image
|
||||
%ImageS = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%textures2D_S_uint_<buffers_num> = OpConstant %uint <buffers_num>
|
||||
%_arr_ImageS_uint_<buffers_num> = OpTypeArray %ImageS %textures2D_S_uint_<buffers_num>
|
||||
%_ptr_UniformConstant__arr_ImageS_uint_<buffers_num> = OpTypePointer UniformConstant %_arr_ImageS_uint_<buffers_num>
|
||||
%_ptr_UniformConstant_ImageS = OpTypePointer UniformConstant %ImageS
|
||||
%SampledImage = OpTypeSampledImage %ImageS
|
||||
)";
|
||||
|
||||
static const char32_t* textures_loaded_types = UR"(
|
||||
%Image = OpTypeImage %float 2D 0 0 0 2 Rgba8
|
||||
%textures2D_uint_<buffers_num> = OpConstant %uint <buffers_num>
|
||||
%_arr_Image_uint_<buffers_num> = OpTypeArray %Image %textures2D_uint_<buffers_num>
|
||||
%_ptr_UniformConstant__arr_Image_uint_<buffers_num> = OpTypePointer UniformConstant %_arr_Image_uint_<buffers_num>
|
||||
%_ptr_UniformConstant_Image = OpTypePointer UniformConstant %Image
|
||||
%ImageL = OpTypeImage %float 2D 0 0 0 2 Rgba8
|
||||
%textures2D_L_uint_<buffers_num> = OpConstant %uint <buffers_num>
|
||||
%_arr_ImageL_uint_<buffers_num> = OpTypeArray %ImageL %textures2D_L_uint_<buffers_num>
|
||||
%_ptr_UniformConstant__arr_ImageL_uint_<buffers_num> = OpTypePointer UniformConstant %_arr_ImageL_uint_<buffers_num>
|
||||
%_ptr_UniformConstant_ImageL = OpTypePointer UniformConstant %ImageL
|
||||
)";
|
||||
|
||||
static const char32_t* samplers_types = UR"(
|
||||
@@ -5333,10 +5512,15 @@ void Spirv::WriteTypes()
|
||||
m_source +=
|
||||
String(storage_buffers_types).ReplaceStr(U"<buffers_num>", String::FromPrintf("%d", m_bind->storage_buffers.buffers_num));
|
||||
}
|
||||
if (m_bind->textures2D.textures_num > 0)
|
||||
if (m_bind_params.textures2d_sampled_num > 0)
|
||||
{
|
||||
m_source += String(m_bind_params.textures2D_without_sampler ? textures_loaded_types : textures_sampled_types)
|
||||
.ReplaceStr(U"<buffers_num>", String::FromPrintf("%d", m_bind->textures2D.textures_num));
|
||||
m_source +=
|
||||
String(textures_sampled_types).ReplaceStr(U"<buffers_num>", String::FromPrintf("%d", m_bind_params.textures2d_sampled_num));
|
||||
}
|
||||
if (m_bind_params.textures2d_storage_num > 0)
|
||||
{
|
||||
m_source +=
|
||||
String(textures_loaded_types).ReplaceStr(U"<buffers_num>", String::FromPrintf("%d", m_bind_params.textures2d_storage_num));
|
||||
}
|
||||
if (m_bind->samplers.samplers_num > 0)
|
||||
{
|
||||
@@ -5402,10 +5586,15 @@ void Spirv::WriteGlobalVariables()
|
||||
vars.Add(String::FromPrintf("%%buf = OpVariable %%_ptr_StorageBuffer__arr_BufferObject_uint_%d StorageBuffer",
|
||||
m_bind->storage_buffers.buffers_num));
|
||||
}
|
||||
if (m_bind->textures2D.textures_num > 0)
|
||||
if (m_bind_params.textures2d_sampled_num > 0)
|
||||
{
|
||||
vars.Add(String::FromPrintf("%%textures2D = OpVariable %%_ptr_UniformConstant__arr_Image_uint_%d UniformConstant",
|
||||
m_bind->textures2D.textures_num));
|
||||
vars.Add(String::FromPrintf("%%textures2D_S = OpVariable %%_ptr_UniformConstant__arr_ImageS_uint_%d UniformConstant",
|
||||
m_bind_params.textures2d_sampled_num));
|
||||
}
|
||||
if (m_bind_params.textures2d_storage_num > 0)
|
||||
{
|
||||
vars.Add(String::FromPrintf("%%textures2D_L = OpVariable %%_ptr_UniformConstant__arr_ImageL_uint_%d UniformConstant",
|
||||
m_bind_params.textures2d_storage_num));
|
||||
}
|
||||
if (m_bind->samplers.samplers_num > 0)
|
||||
{
|
||||
@@ -5817,6 +6006,11 @@ void Spirv::WriteFunctions()
|
||||
m_source += FUNC_ADDC;
|
||||
}
|
||||
|
||||
if (m_code.HasAnyOf({ShaderInstructionType::ImageStoreMip}))
|
||||
{
|
||||
m_source += FUNC_MIPMAP;
|
||||
}
|
||||
|
||||
if (m_code.HasAnyOf({ShaderInstructionType::VCmpOF32, ShaderInstructionType::VCmpUF32}))
|
||||
{
|
||||
m_source += FUNC_ORDERED;
|
||||
|
||||
@@ -210,7 +210,7 @@ public:
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
|
||||
if (nfmt == 9 && dfmt == 10)
|
||||
if ((nfmt == 9 && dfmt == 10) || (nfmt == 0 && dfmt == 10))
|
||||
{
|
||||
// VK_FORMAT_R8G8B8A8_SRGB;
|
||||
m_bits_per_element = 32;
|
||||
@@ -636,27 +636,37 @@ void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t h
|
||||
static const TextureInfo infos[] = {
|
||||
// clang-format off
|
||||
|
||||
// kDataFormatB8G8R8A8UnormSrgb, 512, 512, kTileModeDisplay_LinearAligned
|
||||
{ 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, 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}, } },
|
||||
// kDataFormatB8G8R8A8UnormSrgb, 512, 512, kTileModeThin_1dThin
|
||||
{ 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, 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}, } },
|
||||
// kDataFormatBc3UnormSrgb, 512, 512, kTileModeDisplay_LinearAligned
|
||||
{ 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, 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}, } },
|
||||
// kDataFormatBc3UnormSrgb, 512, 512, kTileModeThin_1dThin
|
||||
{ 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, 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}, } },
|
||||
|
||||
// kDataFormatB8G8R8A8Unorm, 512, 512, kTileModeThin_1dThin
|
||||
{ 10, 0, 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, 0, 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}, } },
|
||||
// kDataFormatB8G8R8A8Unorm, 256, 256, kTileModeThin_2dThin
|
||||
{ 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
|
||||
};
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
|
||||
static void set_image_layout(VkCommandBuffer buffer, VulkanImage* dst_image, uint32_t levels, VkImageAspectFlags aspect_mask,
|
||||
VkImageLayout old_image_layout, VkImageLayout new_image_layout)
|
||||
static void set_image_layout(VkCommandBuffer buffer, VulkanImage* dst_image, uint32_t base_level, uint32_t levels,
|
||||
VkImageAspectFlags aspect_mask, VkImageLayout old_image_layout, VkImageLayout new_image_layout)
|
||||
{
|
||||
EXIT_IF(buffer == nullptr);
|
||||
|
||||
@@ -32,7 +32,7 @@ static void set_image_layout(VkCommandBuffer buffer, VulkanImage* dst_image, uin
|
||||
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_memory_barrier.image = dst_image->image;
|
||||
image_memory_barrier.subresourceRange.aspectMask = aspect_mask;
|
||||
image_memory_barrier.subresourceRange.baseMipLevel = 0;
|
||||
image_memory_barrier.subresourceRange.baseMipLevel = base_level;
|
||||
image_memory_barrier.subresourceRange.levelCount = levels;
|
||||
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
|
||||
image_memory_barrier.subresourceRange.layerCount = 1;
|
||||
@@ -95,7 +95,8 @@ void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, uint32_t
|
||||
|
||||
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
|
||||
|
||||
set_image_layout(vk_buffer, dst_image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
VkBufferImageCopy region {};
|
||||
region.bufferOffset = 0;
|
||||
@@ -112,12 +113,12 @@ 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, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
set_image_layout(vk_buffer, dst_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, TextureVulkanImage* dst_image,
|
||||
const Vector<BufferImageCopy>& regions, uint64_t dst_layout)
|
||||
void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, VulkanImage* dst_image, const Vector<BufferImageCopy>& regions,
|
||||
uint64_t dst_layout)
|
||||
{
|
||||
EXIT_IF(src_buffer == nullptr);
|
||||
EXIT_IF(src_buffer->buffer == nullptr);
|
||||
@@ -137,21 +138,65 @@ void UtilBufferToImage(CommandBuffer* buffer, VulkanBuffer* src_buffer, TextureV
|
||||
region[index].bufferRowLength = (r.width != r.pitch ? r.pitch : 0);
|
||||
region[index].bufferImageHeight = 0;
|
||||
region[index].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region[index].imageSubresource.mipLevel = index;
|
||||
region[index].imageSubresource.mipLevel = r.dst_level;
|
||||
region[index].imageSubresource.baseArrayLayer = 0;
|
||||
region[index].imageSubresource.layerCount = 1;
|
||||
region[index].imageOffset = {0, 0, 0};
|
||||
region[index].imageOffset = {r.dst_x, r.dst_y, 0};
|
||||
region[index].imageExtent = {r.width, r.height, 1};
|
||||
index++;
|
||||
}
|
||||
|
||||
set_image_layout(vk_buffer, dst_image, index, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
set_image_layout(vk_buffer, dst_image, 0, VK_REMAINING_MIP_LEVELS, 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, index, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
/*VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL*/ static_cast<VkImageLayout>(dst_layout));
|
||||
set_image_layout(vk_buffer, dst_image, 0, VK_REMAINING_MIP_LEVELS, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
static_cast<VkImageLayout>(dst_layout));
|
||||
}
|
||||
|
||||
void UtilImageToImage(CommandBuffer* buffer, const Vector<ImageImageCopy>& regions, VulkanImage* dst_image, uint64_t dst_layout)
|
||||
{
|
||||
EXIT_IF(dst_image == nullptr);
|
||||
EXIT_IF(dst_image->image == nullptr);
|
||||
|
||||
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(regions.Size() >= 16);
|
||||
|
||||
set_image_layout(vk_buffer, dst_image, 0, VK_REMAINING_MIP_LEVELS, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
for (const auto& r: regions)
|
||||
{
|
||||
VkImageCopy region;
|
||||
|
||||
auto src_layout = r.src_image->layout;
|
||||
|
||||
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.srcSubresource.mipLevel = r.src_level;
|
||||
region.srcSubresource.baseArrayLayer = 0;
|
||||
region.srcSubresource.layerCount = 1;
|
||||
region.srcOffset = {r.src_x, r.src_y, 0};
|
||||
region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.dstSubresource.mipLevel = r.dst_level;
|
||||
region.dstSubresource.baseArrayLayer = 0;
|
||||
region.dstSubresource.layerCount = 1;
|
||||
region.dstOffset = {r.dst_x, r.dst_y, 0};
|
||||
region.extent = {r.width, r.height, 1};
|
||||
|
||||
set_image_layout(vk_buffer, r.src_image, r.src_level, 1, VK_IMAGE_ASPECT_COLOR_BIT, src_layout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
|
||||
vkCmdCopyImage(vk_buffer, r.src_image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image->image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
set_image_layout(vk_buffer, r.src_image, r.src_level, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
src_layout);
|
||||
}
|
||||
|
||||
set_image_layout(vk_buffer, dst_image, 0, VK_REMAINING_MIP_LEVELS, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
static_cast<VkImageLayout>(dst_layout));
|
||||
}
|
||||
|
||||
void UtilBlitImage(CommandBuffer* buffer, VulkanImage* src_image, VulkanSwapchain* dst_swapchain)
|
||||
@@ -167,9 +212,9 @@ void UtilBlitImage(CommandBuffer* buffer, VulkanImage* src_image, VulkanSwapchai
|
||||
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,
|
||||
set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
set_image_layout(vk_buffer, &swapchain_image, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
set_image_layout(vk_buffer, &swapchain_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
VkImageBlit region {};
|
||||
@@ -197,7 +242,7 @@ void UtilBlitImage(CommandBuffer* buffer, VulkanImage* src_image, VulkanSwapchai
|
||||
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, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
set_image_layout(vk_buffer, src_image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
}
|
||||
|
||||
@@ -286,7 +331,7 @@ void UtilSetDepthLayoutOptimal(DepthStencilVulkanImage* image)
|
||||
aspect_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
|
||||
set_image_layout(vk_buffer, image, 1, aspect_mask, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
set_image_layout(vk_buffer, image, 0, 1, aspect_mask, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
buffer.End();
|
||||
buffer.Execute();
|
||||
@@ -306,15 +351,15 @@ void UtilSetImageLayoutOptimal(VulkanImage* image)
|
||||
|
||||
VkImageAspectFlags aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
set_image_layout(vk_buffer, image, 1, aspect_mask, image->layout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
set_image_layout(vk_buffer, image, 0, 1, aspect_mask, image->layout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
|
||||
buffer.End();
|
||||
buffer.Execute();
|
||||
buffer.WaitForFence();
|
||||
}
|
||||
|
||||
void UtilFillImage(GraphicContext* ctx, TextureVulkanImage* image, const void* src_data, uint64_t size,
|
||||
const Vector<BufferImageCopy>& regions, uint64_t dst_layout)
|
||||
void UtilFillImage(GraphicContext* ctx, VulkanImage* image, const void* src_data, uint64_t size, const Vector<BufferImageCopy>& regions,
|
||||
uint64_t dst_layout)
|
||||
{
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(image == nullptr);
|
||||
@@ -343,6 +388,23 @@ void UtilFillImage(GraphicContext* ctx, TextureVulkanImage* image, const void* s
|
||||
VulkanDeleteBuffer(ctx, &staging_buffer);
|
||||
}
|
||||
|
||||
void UtilFillImage(GraphicContext* ctx, const Vector<ImageImageCopy>& regions, VulkanImage* dst_image, uint64_t dst_layout)
|
||||
{
|
||||
EXIT_IF(ctx == nullptr);
|
||||
EXIT_IF(dst_image == nullptr);
|
||||
|
||||
CommandBuffer buffer;
|
||||
buffer.SetQueue(GraphicContext::QUEUE_UTIL);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(buffer.IsInvalid());
|
||||
|
||||
buffer.Begin();
|
||||
UtilImageToImage(&buffer, regions, dst_image, dst_layout);
|
||||
buffer.End();
|
||||
buffer.Execute();
|
||||
buffer.WaitForFence();
|
||||
}
|
||||
|
||||
void UtilCopyBuffer(VulkanBuffer* src_buffer, VulkanBuffer* dst_buffer, uint64_t size)
|
||||
{
|
||||
EXIT_IF(src_buffer == nullptr);
|
||||
|
||||
@@ -1329,6 +1329,12 @@ static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceK
|
||||
}
|
||||
}
|
||||
|
||||
if (device_features.fragmentStoresAndAtomics != VK_TRUE)
|
||||
{
|
||||
printf("fragmentStoresAndAtomics is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
|
||||
if (!skip_device)
|
||||
{
|
||||
uint32_t extensions_count = 0;
|
||||
@@ -1518,7 +1524,8 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
|
||||
queue_create_info.queueCount = queue_count;
|
||||
queue_create_info.pQueuePriorities = queue_priority.GetDataConst();
|
||||
|
||||
// VkPhysicalDeviceFeatures device_features {};
|
||||
VkPhysicalDeviceFeatures device_features {};
|
||||
device_features.fragmentStoresAndAtomics = VK_TRUE;
|
||||
|
||||
VkDeviceCreateInfo create_info {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
@@ -1530,7 +1537,7 @@ static VkDevice VulkanCreateDevice(VkPhysicalDevice physical_device, VkSurfaceKH
|
||||
create_info.ppEnabledLayerNames = (r->enable_validation_layers ? r->required_layers.GetDataConst() : nullptr);
|
||||
create_info.enabledExtensionCount = device_extensions.Size();
|
||||
create_info.ppEnabledExtensionNames = device_extensions.GetDataConst();
|
||||
create_info.pEnabledFeatures = nullptr; //&device_features;
|
||||
create_info.pEnabledFeatures = &device_features;
|
||||
|
||||
VkDevice device = nullptr;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user