mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
Initial commit
This commit is contained in:
@@ -0,0 +1,432 @@
|
||||
#include "graphics/host_gpu/objects/label.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "kernel/memory.h"
|
||||
#include "common/threads.h"
|
||||
#include "graphics/host_gpu/graphicContext.h"
|
||||
#include "graphics/host_gpu/renderer/render.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
enum LabelStatus {
|
||||
New,
|
||||
Active,
|
||||
ActiveDeleted,
|
||||
NotActive,
|
||||
};
|
||||
|
||||
struct LabelCallbacks {
|
||||
uint64_t* dst_gpu_addr64 = nullptr;
|
||||
uint64_t value64 = 0;
|
||||
uint32_t* dst_gpu_addr32 = nullptr;
|
||||
uint32_t value32 = 0;
|
||||
LabelCallback callback_1 = nullptr;
|
||||
LabelCallback callback_2 = nullptr;
|
||||
uint64_t args[LABEL_ARGS_MAX] = {};
|
||||
};
|
||||
|
||||
struct LabelEvent final {
|
||||
VkDevice device = nullptr;
|
||||
VkEvent event = nullptr;
|
||||
|
||||
~LabelEvent() {
|
||||
if (event != nullptr) {
|
||||
vkDestroyEvent(device, event, nullptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct LabelSubmission {
|
||||
std::shared_ptr<LabelEvent> completion;
|
||||
LabelCallbacks callbacks;
|
||||
};
|
||||
|
||||
struct Label {
|
||||
VkDevice device = nullptr;
|
||||
LabelStatus status = LabelStatus::New;
|
||||
LabelCallbacks callbacks;
|
||||
std::vector<LabelSubmission> submissions;
|
||||
};
|
||||
|
||||
class LabelManager {
|
||||
public:
|
||||
LabelManager() {
|
||||
EXIT_NOT_IMPLEMENTED(!Common::Thread::IsMainThread());
|
||||
Common::Thread t(ThreadRun, this);
|
||||
t.Detach();
|
||||
}
|
||||
~LabelManager() { KYTY_NOT_IMPLEMENTED; }
|
||||
KYTY_CLASS_NO_COPY(LabelManager);
|
||||
|
||||
Label* Create64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value,
|
||||
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args);
|
||||
Label* Create32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value,
|
||||
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args);
|
||||
void Delete(Label* label);
|
||||
void Set(CommandBuffer* buffer, Label* label);
|
||||
void Drain();
|
||||
|
||||
private:
|
||||
static void ThreadRun(void* data);
|
||||
|
||||
template <typename T>
|
||||
Label* Create(GraphicContext* ctx, T* dst_gpu_addr, T value, LabelCallback callback_1,
|
||||
LabelCallback callback_2, const uint64_t* args);
|
||||
bool Remove(Label* label);
|
||||
static void Destroy(Label* label);
|
||||
|
||||
Common::Mutex m_mutex;
|
||||
Common::CondVar m_cond_var;
|
||||
std::vector<Label*> m_labels;
|
||||
uint64_t m_callbacks_in_flight = 0;
|
||||
};
|
||||
|
||||
static LabelManager* g_label_manager = nullptr;
|
||||
static thread_local bool g_in_label_callback = false;
|
||||
|
||||
template <typename T>
|
||||
void WriteGuestLabel(T* address, T value) {
|
||||
LabelWriteGuestMemory(address, &value, sizeof(value));
|
||||
}
|
||||
|
||||
class LabelCallbackScope final {
|
||||
public:
|
||||
LabelCallbackScope() {
|
||||
if (g_in_label_callback) {
|
||||
EXIT("recursive GPU label callback\n");
|
||||
}
|
||||
g_in_label_callback = true;
|
||||
}
|
||||
~LabelCallbackScope() {
|
||||
if (!g_in_label_callback) {
|
||||
EXIT("GPU label callback scope is not active\n");
|
||||
}
|
||||
g_in_label_callback = false;
|
||||
}
|
||||
};
|
||||
|
||||
void LabelManager::ThreadRun(void* data) {
|
||||
auto* manager = static_cast<LabelManager*>(data);
|
||||
|
||||
for (;;) {
|
||||
manager->m_mutex.Lock();
|
||||
|
||||
uint64_t active_count = 0;
|
||||
|
||||
std::vector<Label*> deleted_labels;
|
||||
std::vector<LabelCallbacks> fired_labels;
|
||||
std::vector<LabelSubmission> finished_submissions;
|
||||
deleted_labels.reserve(manager->m_labels.size());
|
||||
|
||||
for (auto& label: manager->m_labels) {
|
||||
for (auto it = label->submissions.begin(); it != label->submissions.end();) {
|
||||
active_count++;
|
||||
|
||||
if (it->completion == nullptr || it->completion->device == nullptr ||
|
||||
it->completion->event == nullptr) {
|
||||
EXIT("GPU label submission has no completion event\n");
|
||||
}
|
||||
const auto status =
|
||||
vkGetEventStatus(it->completion->device, it->completion->event);
|
||||
switch (status) {
|
||||
case VK_EVENT_SET:
|
||||
fired_labels.push_back(it->callbacks);
|
||||
finished_submissions.push_back(*it);
|
||||
it = label->submissions.erase(it);
|
||||
break;
|
||||
case VK_EVENT_RESET: ++it; break;
|
||||
default: EXIT("vkGetEventStatus returned an unexpected result\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (label->submissions.empty()) {
|
||||
switch (label->status) {
|
||||
case LabelStatus::ActiveDeleted: deleted_labels.push_back(label); break;
|
||||
case LabelStatus::Active: label->status = LabelStatus::NotActive; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (active_count == 0) {
|
||||
manager->m_cond_var.Wait(&manager->m_mutex);
|
||||
}
|
||||
if (fired_labels.size() > UINT64_MAX - manager->m_callbacks_in_flight) {
|
||||
EXIT("GPU label callback count overflow\n");
|
||||
}
|
||||
manager->m_callbacks_in_flight += fired_labels.size();
|
||||
|
||||
for (auto& label: deleted_labels) {
|
||||
bool removed = manager->Remove(label);
|
||||
EXIT_NOT_IMPLEMENTED(!removed);
|
||||
}
|
||||
|
||||
manager->m_mutex.Unlock();
|
||||
|
||||
// Each completion event is shared with the recording command buffer's fence retainer.
|
||||
// The event is destroyed only after both the label thread observed it and that command
|
||||
// buffer completed, even when either side wins the race.
|
||||
(void)finished_submissions;
|
||||
|
||||
for (auto& label: deleted_labels) {
|
||||
Destroy(label);
|
||||
}
|
||||
|
||||
for (auto& label: fired_labels) {
|
||||
LabelCallbackScope callback_scope;
|
||||
bool write = true;
|
||||
|
||||
if (label.callback_1 != nullptr) {
|
||||
write = label.callback_1(label.args);
|
||||
}
|
||||
|
||||
if (write && label.dst_gpu_addr64 != nullptr) {
|
||||
// Publishing EOP fences through physical backing keeps a fence word coherent even
|
||||
// when unrelated bytes on its host page are
|
||||
// protected for BufferCache GPU ownership.
|
||||
WriteGuestLabel(label.dst_gpu_addr64, label.value64);
|
||||
|
||||
static std::atomic<uint32_t> log_count {0};
|
||||
if (log_count.fetch_add(1) < 256) {
|
||||
LOGF_COLOR(Log::Color::BrightGreen,
|
||||
"EndOfPipe Signal!!! [0x%016" PRIx64 "] <- 0x%016" PRIx64 "\n",
|
||||
reinterpret_cast<uint64_t>(label.dst_gpu_addr64), label.value64);
|
||||
}
|
||||
}
|
||||
|
||||
if (write && label.dst_gpu_addr32 != nullptr) {
|
||||
WriteGuestLabel(label.dst_gpu_addr32, label.value32);
|
||||
|
||||
static std::atomic<uint32_t> log_count {0};
|
||||
if (log_count.fetch_add(1) < 256) {
|
||||
LOGF_COLOR(Log::Color::BrightGreen,
|
||||
"EndOfPipe Signal!!! [0x%016" PRIx64 "] <- 0x%08" PRIx32 "\n",
|
||||
reinterpret_cast<uint64_t>(label.dst_gpu_addr32), label.value32);
|
||||
}
|
||||
}
|
||||
|
||||
if (label.callback_2 != nullptr) {
|
||||
label.callback_2(label.args);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fired_labels.empty()) {
|
||||
Common::LockGuard lock(manager->m_mutex);
|
||||
if (manager->m_callbacks_in_flight < fired_labels.size()) {
|
||||
EXIT("GPU label callback count underflow\n");
|
||||
}
|
||||
manager->m_callbacks_in_flight -= fired_labels.size();
|
||||
manager->m_cond_var.SignalAll();
|
||||
}
|
||||
|
||||
Common::Thread::SleepMicro(100);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Label* LabelManager::Create(GraphicContext* ctx, T* dst_gpu_addr, T value, LabelCallback callback_1,
|
||||
LabelCallback callback_2, const uint64_t* args) {
|
||||
static_assert(sizeof(T) == sizeof(uint32_t) || sizeof(T) == sizeof(uint64_t));
|
||||
|
||||
EXIT_IF(ctx == nullptr);
|
||||
|
||||
Common::LockGuard lock(m_mutex);
|
||||
|
||||
auto* label = new Label;
|
||||
|
||||
label->status = LabelStatus::New;
|
||||
if constexpr (sizeof(T) == sizeof(uint64_t)) {
|
||||
label->callbacks.dst_gpu_addr64 = dst_gpu_addr;
|
||||
label->callbacks.value64 = value;
|
||||
label->callbacks.dst_gpu_addr32 = nullptr;
|
||||
label->callbacks.value32 = 0;
|
||||
} else {
|
||||
label->callbacks.dst_gpu_addr32 = dst_gpu_addr;
|
||||
label->callbacks.value32 = value;
|
||||
label->callbacks.dst_gpu_addr64 = nullptr;
|
||||
label->callbacks.value64 = 0;
|
||||
}
|
||||
label->device = ctx->device;
|
||||
label->callbacks.callback_1 = callback_1;
|
||||
label->callbacks.callback_2 = callback_2;
|
||||
|
||||
if (args != nullptr) {
|
||||
for (int i = 0; i < LABEL_ARGS_MAX; i++) {
|
||||
label->callbacks.args[i] = args[i];
|
||||
}
|
||||
}
|
||||
|
||||
m_labels.push_back(label);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
Label* LabelManager::Create64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value,
|
||||
LabelCallback callback_1, LabelCallback callback_2,
|
||||
const uint64_t* args) {
|
||||
return Create(ctx, dst_gpu_addr, value, callback_1, callback_2, args);
|
||||
}
|
||||
|
||||
Label* LabelManager::Create32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value,
|
||||
LabelCallback callback_1, LabelCallback callback_2,
|
||||
const uint64_t* args) {
|
||||
return Create(ctx, dst_gpu_addr, value, callback_1, callback_2, args);
|
||||
}
|
||||
|
||||
bool LabelManager::Remove(Label* label) {
|
||||
EXIT_IF(label == nullptr);
|
||||
EXIT_IF(label->device == nullptr);
|
||||
|
||||
Common::LockGuard lock(m_mutex);
|
||||
|
||||
const auto it = std::find(m_labels.begin(), m_labels.end(), label);
|
||||
EXIT_NOT_IMPLEMENTED(it == m_labels.end());
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(label->status != LabelStatus::NotActive &&
|
||||
label->status != LabelStatus::Active &&
|
||||
label->status != LabelStatus::ActiveDeleted);
|
||||
|
||||
if (!label->submissions.empty()) {
|
||||
label->status = LabelStatus::ActiveDeleted;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_labels.erase(it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LabelManager::Destroy(Label* label) {
|
||||
EXIT_IF(label == nullptr);
|
||||
EXIT_IF(label->device == nullptr);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(!label->submissions.empty());
|
||||
|
||||
delete label;
|
||||
}
|
||||
|
||||
void LabelManager::Delete(Label* label) {
|
||||
if (Remove(label)) {
|
||||
Destroy(label);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelManager::Set(CommandBuffer* buffer, Label* label) {
|
||||
EXIT_IF(label == nullptr);
|
||||
EXIT_IF(buffer == nullptr);
|
||||
EXIT_IF(buffer->IsInvalid());
|
||||
EXIT_IF(label->device == nullptr);
|
||||
|
||||
Common::LockGuard lock(m_mutex);
|
||||
|
||||
const auto it = std::find(m_labels.begin(), m_labels.end(), label);
|
||||
EXIT_NOT_IMPLEMENTED(it == m_labels.end());
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(label->status != LabelStatus::New &&
|
||||
label->status != LabelStatus::NotActive &&
|
||||
label->status != LabelStatus::Active);
|
||||
|
||||
label->status = LabelStatus::Active;
|
||||
|
||||
LabelSubmission submission {};
|
||||
submission.callbacks = label->callbacks;
|
||||
submission.completion = std::make_shared<LabelEvent>();
|
||||
submission.completion->device = label->device;
|
||||
|
||||
auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()];
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(vk_buffer == nullptr);
|
||||
|
||||
VkEventCreateInfo create_info {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
|
||||
create_info.pNext = nullptr;
|
||||
create_info.flags = 0;
|
||||
|
||||
vkCreateEvent(label->device, &create_info, nullptr, &submission.completion->event);
|
||||
EXIT_NOT_IMPLEMENTED(submission.completion->event == nullptr);
|
||||
buffer->RetainResourceUntilFence(submission.completion);
|
||||
|
||||
// Labels can be reused before an earlier end-of-pipe event has been
|
||||
// observed by the polling thread. Capture a separate Vulkan event and
|
||||
// callback snapshot for each set so older writes are not lost.
|
||||
vkResetEvent(label->device, submission.completion->event);
|
||||
vkCmdSetEvent(vk_buffer, submission.completion->event, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
|
||||
|
||||
label->submissions.push_back(submission);
|
||||
|
||||
m_cond_var.SignalAll();
|
||||
}
|
||||
|
||||
void LabelManager::Drain() {
|
||||
m_mutex.Lock();
|
||||
for (;;) {
|
||||
const bool pending = std::any_of(m_labels.begin(), m_labels.end(), [](const Label* label) {
|
||||
return !label->submissions.empty();
|
||||
});
|
||||
if (!pending && m_callbacks_in_flight == 0) {
|
||||
m_mutex.Unlock();
|
||||
return;
|
||||
}
|
||||
m_cond_var.SignalAll();
|
||||
m_cond_var.Wait(&m_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelInit() {
|
||||
EXIT_IF(g_label_manager != nullptr);
|
||||
|
||||
g_label_manager = new LabelManager;
|
||||
}
|
||||
|
||||
Label* LabelCreate64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value,
|
||||
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args) {
|
||||
EXIT_IF(g_label_manager == nullptr);
|
||||
|
||||
return g_label_manager->Create64(ctx, dst_gpu_addr, value, callback_1, callback_2, args);
|
||||
}
|
||||
|
||||
Label* LabelCreate32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value,
|
||||
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args) {
|
||||
EXIT_IF(g_label_manager == nullptr);
|
||||
|
||||
return g_label_manager->Create32(ctx, dst_gpu_addr, value, callback_1, callback_2, args);
|
||||
}
|
||||
|
||||
void LabelDelete(Label* label) {
|
||||
EXIT_IF(g_label_manager == nullptr);
|
||||
|
||||
g_label_manager->Delete(label);
|
||||
}
|
||||
|
||||
void LabelSet(CommandBuffer* buffer, Label* label) {
|
||||
EXIT_IF(g_label_manager == nullptr);
|
||||
|
||||
g_label_manager->Set(buffer, label);
|
||||
}
|
||||
|
||||
void LabelDrain() {
|
||||
EXIT_IF(g_label_manager == nullptr);
|
||||
g_label_manager->Drain();
|
||||
}
|
||||
|
||||
void LabelWriteGuestMemory(void* address, const void* data, uint64_t size) {
|
||||
if (address == nullptr || data == nullptr || size == 0) {
|
||||
EXIT("invalid guest label write\n");
|
||||
}
|
||||
if (!Libs::LibKernel::Memory::TryWriteBacking(reinterpret_cast<uint64_t>(address), data, size)) {
|
||||
std::memcpy(address, data, static_cast<size_t>(size));
|
||||
}
|
||||
}
|
||||
|
||||
bool LabelInCallback() noexcept {
|
||||
return g_in_label_callback;
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_LABEL_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_LABEL_H_
|
||||
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
struct Label;
|
||||
class CommandBuffer;
|
||||
struct GraphicContext;
|
||||
|
||||
void LabelInit();
|
||||
|
||||
constexpr int LABEL_ARGS_MAX = 5;
|
||||
using LabelCallback = bool (*)(const uint64_t* args);
|
||||
|
||||
Label* LabelCreate64(GraphicContext* ctx, uint64_t* dst_gpu_addr, uint64_t value,
|
||||
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args);
|
||||
Label* LabelCreate32(GraphicContext* ctx, uint32_t* dst_gpu_addr, uint32_t value,
|
||||
LabelCallback callback_1, LabelCallback callback_2, const uint64_t* args);
|
||||
void LabelDelete(Label* label);
|
||||
void LabelSet(CommandBuffer* buffer, Label* label);
|
||||
void LabelDrain();
|
||||
void LabelWriteGuestMemory(void* address, const void* data, uint64_t size);
|
||||
[[nodiscard]] bool LabelInCallback() noexcept;
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_LABEL_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,140 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_TEXTURECOMMON_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_TEXTURECOMMON_H_
|
||||
|
||||
#include "common/abi.h"
|
||||
#include "common/common.h"
|
||||
#include "graphics/guest_gpu/tile.h"
|
||||
#include "graphics/host_gpu/utils.h"
|
||||
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
struct GraphicContext;
|
||||
struct VulkanImage;
|
||||
struct VulkanMemory;
|
||||
|
||||
enum class TextureFormatUsage : uint32_t {
|
||||
None = 0,
|
||||
Sampled = 1u << 0u,
|
||||
Storage = 1u << 1u,
|
||||
};
|
||||
|
||||
constexpr TextureFormatUsage operator|(TextureFormatUsage lhs, TextureFormatUsage rhs) {
|
||||
return static_cast<TextureFormatUsage>(static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs));
|
||||
}
|
||||
|
||||
constexpr TextureFormatUsage operator&(TextureFormatUsage lhs, TextureFormatUsage rhs) {
|
||||
return static_cast<TextureFormatUsage>(static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs));
|
||||
}
|
||||
|
||||
constexpr TextureFormatUsage operator~(TextureFormatUsage usage) {
|
||||
return static_cast<TextureFormatUsage>(~static_cast<uint32_t>(usage));
|
||||
}
|
||||
|
||||
constexpr TextureFormatUsage& operator|=(TextureFormatUsage& lhs, TextureFormatUsage rhs) {
|
||||
lhs = lhs | rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
constexpr bool TextureHasFormatUsage(TextureFormatUsage usage, TextureFormatUsage flag) {
|
||||
return (static_cast<uint32_t>(usage & flag) == static_cast<uint32_t>(flag));
|
||||
}
|
||||
|
||||
enum class TextureUploadDestination { MipLevels, MipAtlas };
|
||||
|
||||
enum class TextureUploadSliceLayout { MipChainPerSlice, MipLevelPerSlice };
|
||||
|
||||
struct RenderTargetFormatInfo {
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
uint32_t bytes_per_element = 0;
|
||||
};
|
||||
|
||||
struct TextureUploadLayout {
|
||||
uint32_t tile = 0;
|
||||
uint32_t pitch = 0;
|
||||
uint64_t slice_stride = 0;
|
||||
uint64_t source_slice_stride = 0;
|
||||
bool fmt_tiled_render_target = false;
|
||||
bool fmt_tiled_standard256b = false;
|
||||
bool fmt_tiled_standard4kb = false;
|
||||
bool fmt_tiled_standard64kb = false;
|
||||
bool fmt_tiled_depth = false;
|
||||
bool volume_texture = false;
|
||||
TileSizeOffset level_sizes[16] = {};
|
||||
TilePaddedSize padded_sizes[16] = {};
|
||||
};
|
||||
|
||||
struct TextureImageCreateParams {
|
||||
uint32_t fmt = 0;
|
||||
uint64_t width = 0;
|
||||
uint64_t height = 0;
|
||||
uint32_t base_level = 0;
|
||||
uint64_t levels = 1;
|
||||
uint32_t depth = 1;
|
||||
uint64_t type = 0;
|
||||
uint64_t swizzle = 0;
|
||||
TextureFormatUsage format_usage = TextureFormatUsage::Sampled;
|
||||
TextureFormatUsage required_format_usage = TextureFormatUsage::Sampled;
|
||||
TextureFormatUsage view_usage = TextureFormatUsage::Sampled;
|
||||
TextureUploadDestination image_layout = TextureUploadDestination::MipLevels;
|
||||
bool allow_cube_view = false;
|
||||
bool compatible_format_views = false;
|
||||
bool storage_swizzle_fallback = false;
|
||||
const char* owner = nullptr;
|
||||
};
|
||||
|
||||
VkComponentSwizzle TextureGetComponentSwizzle(uint8_t s);
|
||||
VkComponentMapping TextureGetComponentMapping(uint32_t swizzle);
|
||||
bool TextureCheckFormat(GraphicContext* ctx, VkImageCreateInfo* image_info);
|
||||
bool TextureCheckStorageSwizzle(VkImageCreateInfo* image_info, VkComponentMapping* components);
|
||||
VkImageUsageFlags TextureGetUsage(TextureFormatUsage usage);
|
||||
VkImageUsageFlags TextureGetViewUsage(TextureFormatUsage usage);
|
||||
VkFormat TextureGetFormat(uint32_t fmt, TextureFormatUsage usage);
|
||||
RenderTargetFormatInfo TextureGetRenderTargetFormat(uint32_t layout, uint32_t type, uint32_t order);
|
||||
uint32_t TextureGetAtlasSliceYStride(VkFormat format, uint32_t mip_height, uint32_t depth,
|
||||
uint64_t levels);
|
||||
uint32_t TextureCalcStackedImageHeight(VkFormat format, uint32_t height, uint32_t depth,
|
||||
uint64_t levels);
|
||||
uint32_t TextureCalcMipmapAtlasImageHeight(VkFormat format, uint32_t width, uint32_t height,
|
||||
uint32_t depth, uint64_t levels);
|
||||
bool TextureIs3DTexture(uint64_t type);
|
||||
bool TextureIsCubeTexture(uint64_t type);
|
||||
bool TextureIsLayeredTexture(uint64_t type);
|
||||
bool TextureCanCreateCubeView(uint64_t type, uint32_t base_array, uint32_t layer_count);
|
||||
VkComponentMapping TextureCreateImage(GraphicContext* ctx, VulkanImage* vk_obj, VulkanMemory* mem,
|
||||
const TextureImageCreateParams& params);
|
||||
void TextureCreateImageViews(GraphicContext* ctx, VulkanImage* vk_obj,
|
||||
VkComponentMapping components, uint64_t type, uint32_t base_array,
|
||||
uint32_t base_level, uint32_t level_count, uint32_t depth,
|
||||
bool allow_cube_view, TextureFormatUsage view_usage);
|
||||
TextureUploadLayout TextureCalcUploadLayout(uint32_t fmt, uint64_t width, uint64_t height,
|
||||
uint64_t levels, uint32_t depth, uint64_t pitch,
|
||||
uint64_t tile, uint64_t upload_size,
|
||||
bool allow_depth_tile,
|
||||
bool require_single_mip_small_tiles,
|
||||
bool volume_texture, const char* owner);
|
||||
uint64_t TextureUploadSliceSourceOffset(const TextureUploadLayout& layout, uint32_t level,
|
||||
uint32_t slice,
|
||||
TextureUploadSliceLayout source_slice_layout);
|
||||
uint64_t TextureCalcUploadSize(const TextureUploadLayout& layout,
|
||||
const std::vector<BufferImageCopy>& regions, uint64_t levels,
|
||||
uint32_t depth, TextureUploadSliceLayout source_slice_layout);
|
||||
std::vector<BufferImageCopy>
|
||||
TextureBuildUploadRegions(const TextureUploadLayout& layout, VkFormat image_format, uint32_t width,
|
||||
uint32_t height, uint32_t depth, uint64_t levels, bool array_texture,
|
||||
bool volume_texture, TextureUploadDestination destination,
|
||||
TextureUploadSliceLayout slice_layout);
|
||||
void TextureCopyBufferBytes(GraphicContext* ctx, VulkanBuffer* src_buffer,
|
||||
uint64_t src_buffer_offset, uint64_t copy_size, UtilScratchBuffer* dst);
|
||||
void TextureUploadGuestImage(GraphicContext* ctx, VulkanImage* vk_obj, const void* src_data,
|
||||
uint64_t size, const std::vector<BufferImageCopy>& regions,
|
||||
const TextureUploadLayout& layout, uint32_t fmt, uint64_t width,
|
||||
uint64_t height, uint32_t depth, uint64_t levels,
|
||||
TextureUploadSliceLayout source_slice_layout, const char* owner,
|
||||
uint64_t dst_layout);
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_OBJECTS_TEXTURECOMMON_H_ */
|
||||
Reference in New Issue
Block a user