mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-09 21:31:04 +00:00
amdgpu: Split liverpool registers and cleanup (#3707)
This commit is contained in:
146
src/shader_recompiler/resource.h
Normal file
146
src/shader_recompiler/resource.h
Normal file
@@ -0,0 +1,146 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
#include "shader_recompiler/ir/type.h"
|
||||
#include "video_core/amdgpu/resource.h"
|
||||
|
||||
#include <boost/container/static_vector.hpp>
|
||||
|
||||
namespace Shader {
|
||||
|
||||
static constexpr u32 NUM_USER_DATA_REGS = 16;
|
||||
static constexpr u32 NUM_IMAGES = 64;
|
||||
static constexpr u32 NUM_BUFFERS = 40;
|
||||
static constexpr u32 NUM_SAMPLERS = 16;
|
||||
static constexpr u32 NUM_FMASKS = 8;
|
||||
|
||||
enum class BufferType : u32 {
|
||||
Guest,
|
||||
Flatbuf,
|
||||
BdaPagetable,
|
||||
FaultBuffer,
|
||||
GdsBuffer,
|
||||
SharedMemory,
|
||||
};
|
||||
|
||||
struct Info;
|
||||
|
||||
struct BufferResource {
|
||||
u32 sharp_idx;
|
||||
IR::Type used_types;
|
||||
AmdGpu::Buffer inline_cbuf;
|
||||
BufferType buffer_type;
|
||||
u8 instance_attrib{};
|
||||
bool is_written{};
|
||||
bool is_formatted{};
|
||||
|
||||
bool IsSpecial() const noexcept {
|
||||
return buffer_type != BufferType::Guest;
|
||||
}
|
||||
|
||||
bool IsStorage([[maybe_unused]] const AmdGpu::Buffer buffer) const noexcept {
|
||||
// When using uniform buffers, a size is required at compilation time, so we need to
|
||||
// either compile a lot of shader specializations to handle each size or just force it to
|
||||
// the maximum possible size always. However, for some vendors the shader-supplied size is
|
||||
// used for bounds checking uniform buffer accesses, so the latter would effectively turn
|
||||
// off buffer robustness behavior. Instead, force storage buffers which are bounds checked
|
||||
// using the actual buffer size. We are assuming the performance hit from this is
|
||||
// acceptable.
|
||||
return true; // buffer.GetSize() > profile.max_ubo_size || is_written;
|
||||
}
|
||||
|
||||
constexpr AmdGpu::Buffer GetSharp(const auto& info) const noexcept {
|
||||
const auto buffer =
|
||||
inline_cbuf ? inline_cbuf : info.template ReadUdSharp<AmdGpu::Buffer>(sharp_idx);
|
||||
if (!buffer.Valid()) {
|
||||
LOG_DEBUG(Render, "Encountered invalid buffer sharp");
|
||||
return AmdGpu::Buffer::Null();
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
using BufferResourceList = boost::container::static_vector<BufferResource, NUM_BUFFERS>;
|
||||
|
||||
struct ImageResource {
|
||||
u32 sharp_idx;
|
||||
bool is_depth{};
|
||||
bool is_atomic{};
|
||||
bool is_array{};
|
||||
bool is_written{};
|
||||
bool is_r128{};
|
||||
|
||||
constexpr AmdGpu::Image GetSharp(const auto& info) const noexcept {
|
||||
AmdGpu::Image image{};
|
||||
if (!is_r128) {
|
||||
image = info.template ReadUdSharp<AmdGpu::Image>(sharp_idx);
|
||||
} else {
|
||||
const auto raw = info.template ReadUdSharp<u128>(sharp_idx);
|
||||
std::memcpy(&image, &raw, sizeof(raw));
|
||||
}
|
||||
if (!image.Valid()) {
|
||||
LOG_DEBUG(Render_Vulkan, "Encountered invalid image sharp");
|
||||
image = AmdGpu::Image::Null(is_depth);
|
||||
} else if (is_depth) {
|
||||
const auto data_fmt = image.GetDataFmt();
|
||||
if (data_fmt != AmdGpu::DataFormat::Format16 &&
|
||||
data_fmt != AmdGpu::DataFormat::Format32) {
|
||||
LOG_DEBUG(Render_Vulkan,
|
||||
"Encountered non-depth image used with depth instruction!");
|
||||
image = AmdGpu::Image::Null(true);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
};
|
||||
using ImageResourceList = boost::container::static_vector<ImageResource, NUM_IMAGES>;
|
||||
|
||||
struct SamplerResource {
|
||||
u32 sharp_idx;
|
||||
AmdGpu::Sampler inline_sampler;
|
||||
u32 is_inline_sampler : 1;
|
||||
u32 associated_image : 4;
|
||||
u32 disable_aniso : 1;
|
||||
|
||||
constexpr AmdGpu::Sampler GetSharp(const auto& info) const noexcept {
|
||||
return is_inline_sampler ? inline_sampler
|
||||
: info.template ReadUdSharp<AmdGpu::Sampler>(sharp_idx);
|
||||
}
|
||||
};
|
||||
using SamplerResourceList = boost::container::static_vector<SamplerResource, NUM_SAMPLERS>;
|
||||
|
||||
struct FMaskResource {
|
||||
u32 sharp_idx;
|
||||
|
||||
constexpr AmdGpu::Image GetSharp(const auto& info) const noexcept {
|
||||
return info.template ReadUdSharp<AmdGpu::Image>(sharp_idx);
|
||||
}
|
||||
};
|
||||
using FMaskResourceList = boost::container::static_vector<FMaskResource, NUM_FMASKS>;
|
||||
|
||||
struct PushData {
|
||||
static constexpr u32 XOffsetIndex = 0;
|
||||
static constexpr u32 YOffsetIndex = 1;
|
||||
static constexpr u32 XScaleIndex = 2;
|
||||
static constexpr u32 YScaleIndex = 3;
|
||||
static constexpr u32 UdRegsIndex = 4;
|
||||
static constexpr u32 BufOffsetIndex = UdRegsIndex + NUM_USER_DATA_REGS / 4;
|
||||
|
||||
float xoffset;
|
||||
float yoffset;
|
||||
float xscale;
|
||||
float yscale;
|
||||
std::array<u32, NUM_USER_DATA_REGS> ud_regs;
|
||||
std::array<u8, NUM_BUFFERS> buf_offsets;
|
||||
|
||||
void AddOffset(u32 binding, u32 offset) {
|
||||
ASSERT(offset < 256 && binding < buf_offsets.size());
|
||||
buf_offsets[binding] = offset;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(PushData) <= 128,
|
||||
"PushData size is greater than minimum size guaranteed by Vulkan spec");
|
||||
|
||||
} // namespace Shader
|
||||
Reference in New Issue
Block a user