mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
graphics: unify buffer bindings and depth target handling
This commit is contained in:
@@ -213,6 +213,8 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std
|
||||
}
|
||||
return false;
|
||||
}
|
||||
next.buffer_offset_dword = static_cast<uint32_t>(next.user_data_registers.size());
|
||||
next.buffer_offset_count = static_cast<uint32_t>(program.info.buffers.size());
|
||||
|
||||
if (!program.info.buffers.empty()) {
|
||||
std::vector<uint32_t> resources(program.info.buffers.size());
|
||||
@@ -269,8 +271,8 @@ bool AllocateBindings(Program& program, const BindingLayoutOptions& options, std
|
||||
|
||||
const auto available_push_dwords = (MaxPushConstantBytes - options.push_constant_offset) / 4u;
|
||||
const auto push_limit = std::min(options.max_push_dwords, available_push_dwords);
|
||||
if (next.user_data_registers.size() <= push_limit) {
|
||||
next.push_constant_size = static_cast<uint32_t>(next.user_data_registers.size() * 4u);
|
||||
if (next.ShaderDataDwords() <= push_limit) {
|
||||
next.push_constant_size = next.ShaderDataDwords() * sizeof(uint32_t);
|
||||
} else {
|
||||
AddBinding(next, DescriptorBindingKind::UserData);
|
||||
}
|
||||
|
||||
@@ -249,6 +249,12 @@ bool MaterializeResources(const Program& program, const SrtRuntime& runtime,
|
||||
auto cursor = values.begin();
|
||||
next.buffers.assign(cursor, cursor + program.info.buffers.size());
|
||||
cursor += program.info.buffers.size();
|
||||
for (auto& descriptor: next.buffers) {
|
||||
ShaderBufferResource buffer;
|
||||
if (DecodeBufferDescriptor(descriptor, buffer) && buffer.Type() != 0) {
|
||||
descriptor.dwords.fill(0);
|
||||
}
|
||||
}
|
||||
next.images.assign(cursor, cursor + program.info.images.size());
|
||||
cursor += program.info.images.size();
|
||||
for (auto& descriptor: next.images) {
|
||||
|
||||
@@ -705,9 +705,15 @@ struct BindingLayout {
|
||||
uint32_t descriptor_set = 0;
|
||||
uint32_t push_constant_offset = 0;
|
||||
uint32_t push_constant_size = 0;
|
||||
uint32_t buffer_offset_dword = 0;
|
||||
uint32_t buffer_offset_count = 0;
|
||||
std::vector<uint32_t> user_data_registers;
|
||||
std::vector<DescriptorBinding> descriptors;
|
||||
|
||||
[[nodiscard]] uint32_t ShaderDataDwords() const {
|
||||
return buffer_offset_dword + (buffer_offset_count + 3u) / 4u;
|
||||
}
|
||||
|
||||
bool operator==(const BindingLayout& other) const = default;
|
||||
};
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ bool ValidateNativeProgram(const IR::Program& program, std::string* error) {
|
||||
if (!program.srt.reads.empty()) {
|
||||
Expect(Kind::FlattenedSrt);
|
||||
}
|
||||
if (!program.bindings.user_data_registers.empty() && program.bindings.push_constant_size == 0) {
|
||||
if (program.bindings.ShaderDataDwords() != 0 && program.bindings.push_constant_size == 0) {
|
||||
Expect(Kind::UserData);
|
||||
}
|
||||
|
||||
@@ -263,8 +263,10 @@ bool ValidateNativeProgram(const IR::Program& program, std::string* error) {
|
||||
}
|
||||
}
|
||||
const auto has_user_storage = present[static_cast<size_t>(Kind::UserData)];
|
||||
if ((!has_user_storage &&
|
||||
program.bindings.push_constant_size != program.bindings.user_data_registers.size() * 4u) ||
|
||||
if (program.bindings.buffer_offset_dword != program.bindings.user_data_registers.size() ||
|
||||
program.bindings.buffer_offset_count != program.info.buffers.size() ||
|
||||
(!has_user_storage &&
|
||||
program.bindings.push_constant_size != program.bindings.ShaderDataDwords() * 4u) ||
|
||||
(has_user_storage && program.bindings.push_constant_size != 0) ||
|
||||
!std::is_sorted(program.bindings.user_data_registers.begin(),
|
||||
program.bindings.user_data_registers.end()) ||
|
||||
@@ -408,10 +410,10 @@ bool ProgramRequiresExactSubgroupSize(const IR::Program& program) {
|
||||
}
|
||||
|
||||
bool EmitProgram(const IR::Program& program, const IR::ResourceSnapshot& resources,
|
||||
const ShaderVertexInputInfo* vertex_input_info,
|
||||
const ShaderPixelInputInfo* pixel_input_info,
|
||||
const ShaderComputeInputInfo* compute_input_info, std::vector<uint32_t>& spirv,
|
||||
std::string* error) {
|
||||
const ShaderVertexInputInfo* vertex_input_info,
|
||||
const ShaderPixelInputInfo* pixel_input_info,
|
||||
const ShaderComputeInputInfo* compute_input_info, std::vector<uint32_t>& spirv,
|
||||
std::string* error) {
|
||||
using namespace Emitter;
|
||||
|
||||
if (program.stage != ShaderType::Compute && program.stage != ShaderType::Vertex &&
|
||||
|
||||
@@ -134,7 +134,7 @@ bool UserDataDwordIndex(const EmitterState& state, IR::Register reg, uint32_t& d
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t EmitVsharpDwordLoad(EmitterState& state, uint32_t dword_index) {
|
||||
uint32_t EmitShaderDataDwordLoad(EmitterState& state, uint32_t dword_index) {
|
||||
if (state.push_constant_variable != 0) {
|
||||
const auto pointer = state.builder.AllocateId();
|
||||
const auto value = state.builder.AllocateId();
|
||||
@@ -172,7 +172,7 @@ uint32_t InitialRegisterValue(const EmitterState& state, IR::Register reg) {
|
||||
uint32_t EmitInitialRegisterValue(EmitterState& state, IR::Register reg) {
|
||||
uint32_t dword_index = 0;
|
||||
if (UserDataDwordIndex(state, reg, dword_index)) {
|
||||
return EmitVsharpDwordLoad(state, dword_index);
|
||||
return EmitShaderDataDwordLoad(state, dword_index);
|
||||
}
|
||||
return ConstantU32(state, InitialRegisterValue(state, reg));
|
||||
}
|
||||
@@ -1064,6 +1064,7 @@ void EmitFunction(EmitterState& state, const IR::Program& program) {
|
||||
EmitComputeInputRegisters(state);
|
||||
EmitPixelInputRegisters(state);
|
||||
EmitVertexInputRegisters(state);
|
||||
EmitStorageBufferOffsets(state);
|
||||
if (state.dispatcher_fallback) {
|
||||
EmitDispatcherFunction(state, program);
|
||||
state.builder.AddFunction({OpFunctionEnd});
|
||||
|
||||
@@ -355,6 +355,7 @@ struct EmitterState {
|
||||
uint32_t storage_buffer_array_type = 0;
|
||||
uint32_t ptr_storage_buffer_array = 0;
|
||||
uint32_t storage_buffer_variable = 0;
|
||||
std::array<uint32_t, IR::ShaderInfo::MaxBuffers> storage_buffer_offsets {};
|
||||
uint32_t address_memory_array_type = 0;
|
||||
uint32_t ptr_address_memory_array = 0;
|
||||
uint32_t address_memory_variable = 0;
|
||||
@@ -837,6 +838,8 @@ uint32_t EmitNotEqualZeroBool(EmitterState& state, uint32_t value);
|
||||
uint32_t EmitSelectU32Value(EmitterState& state, uint32_t condition, uint32_t true_value,
|
||||
uint32_t false_value);
|
||||
|
||||
uint32_t EmitShaderDataDwordLoad(EmitterState& state, uint32_t dword_index);
|
||||
|
||||
uint32_t EmitByteAddress(EmitterState& state, const IR::Instruction& inst, uint32_t first_src,
|
||||
uint32_t src_count);
|
||||
|
||||
@@ -854,6 +857,8 @@ uint32_t EmitOptionalLogicalAndBool(EmitterState& state, uint32_t lhs, uint32_t
|
||||
|
||||
bool IsStorageBufferMemoryKind(IR::ResourceKind kind);
|
||||
|
||||
void EmitStorageBufferOffsets(EmitterState& state);
|
||||
|
||||
uint32_t EmitBufferAddressFromParts(EmitterState& state, const IR::Instruction& inst,
|
||||
uint32_t index, uint32_t offset, uint32_t soffset);
|
||||
|
||||
|
||||
@@ -210,6 +210,17 @@ bool IsStorageBufferMemoryKind(IR::ResourceKind kind) {
|
||||
}
|
||||
}
|
||||
|
||||
void EmitStorageBufferOffsets(EmitterState& state) {
|
||||
for (uint32_t i = 0; i < state.program.bindings.buffer_offset_count; i++) {
|
||||
const auto word = EmitShaderDataDwordLoad(
|
||||
state, state.program.bindings.buffer_offset_dword + i / 4u);
|
||||
const auto shift = ConstantU32(state, (i % 4u) * 8u + 2u);
|
||||
state.storage_buffer_offsets[i] = EmitBinaryU32(
|
||||
state, OpBitwiseAnd,
|
||||
EmitBinaryU32(state, OpShiftRightLogical, word, shift), ConstantU32(state, 0x3fu));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EmitBufferAddressFromParts(EmitterState& state, const IR::Instruction& inst,
|
||||
uint32_t index, uint32_t offset, uint32_t soffset) {
|
||||
const auto& mem = inst.memory;
|
||||
@@ -398,6 +409,15 @@ StorageBufferBindingForMemory(EmitterState& state, const IR::MemoryInfo& mem, ui
|
||||
return binding;
|
||||
}
|
||||
|
||||
uint32_t EmitStorageBufferIndex(EmitterState& state, const IR::MemoryInfo& mem, uint32_t index,
|
||||
uint32_t use_pc) {
|
||||
if (IsFlatMemoryKind(mem.kind)) {
|
||||
return index;
|
||||
}
|
||||
const auto binding = StorageBufferBindingForMemory(state, mem, use_pc);
|
||||
return EmitAddU32(state, index, state.storage_buffer_offsets[binding.array_index]);
|
||||
}
|
||||
|
||||
uint32_t EmitStorageBufferObjectPointer(EmitterState& state, const IR::MemoryInfo& mem,
|
||||
uint32_t use_pc) {
|
||||
if (IsFlatMemoryKind(mem.kind)) {
|
||||
@@ -422,7 +442,8 @@ uint32_t EmitStorageBufferObjectPointer(EmitterState& state, const IR::MemoryInf
|
||||
}
|
||||
|
||||
uint32_t EmitStorageBufferElementInBounds(EmitterState& state, const IR::MemoryInfo& mem,
|
||||
uint32_t index, uint32_t use_pc) {
|
||||
uint32_t index, uint32_t use_pc) {
|
||||
index = EmitStorageBufferIndex(state, mem, index, use_pc);
|
||||
const auto object = EmitStorageBufferObjectPointer(state, mem, use_pc);
|
||||
const auto length = state.builder.AllocateId();
|
||||
const auto in_bounds = state.builder.AllocateId();
|
||||
@@ -432,7 +453,8 @@ uint32_t EmitStorageBufferElementInBounds(EmitterState& state, const IR::MemoryI
|
||||
}
|
||||
|
||||
uint32_t EmitStorageBufferElementPointer(EmitterState& state, const IR::MemoryInfo& mem,
|
||||
uint32_t index, uint32_t use_pc) {
|
||||
uint32_t index, uint32_t use_pc) {
|
||||
index = EmitStorageBufferIndex(state, mem, index, use_pc);
|
||||
if (IsFlatMemoryKind(mem.kind)) {
|
||||
if (state.address_memory_variable == 0) {
|
||||
ExitDescriptorBindingFailure(state, IR::DescriptorBindingKind::AddressMemory,
|
||||
|
||||
Reference in New Issue
Block a user