mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-30 09:08:19 +00:00
shader: add BVH8 intersections and instance transforms
This commit is contained in:
1 parent
bfd4c34b88
commit
5eab0ec738
21 files changed
+964
-15
No files matched your search
@@ -281,6 +281,7 @@ Opcode DecodeMimgOpcode(uint32_t opcode, const MimgSampleInfo* sample, const Mim
|
||||
case 0x09u: return Opcode::IMAGE_STORE_MIP;
|
||||
case 0x0eu: return Opcode::IMAGE_GET_RESINFO;
|
||||
case 0x60u: return Opcode::IMAGE_GET_LOD;
|
||||
case 0xe5u: return Opcode::IMAGE_BVH8_INTERSECT_RAY;
|
||||
case 0xe6u:
|
||||
case 0xe7u: return Opcode::IMAGE_BVH_INTERSECT_RAY;
|
||||
default: return Opcode::UNSUPPORTED;
|
||||
@@ -297,6 +298,7 @@ uint32_t DecodeMimgAddressComponents(uint32_t opcode, ImageDimension dimension,
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case 0xe5u:
|
||||
case 0xe6u: return 11u;
|
||||
case 0xe7u: return 12u;
|
||||
case 0x0eu: return 1u;
|
||||
@@ -427,6 +429,36 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
"BVH intersection requires full-float ray DWORDs and R128/dmask:0xf");
|
||||
}
|
||||
|
||||
if (opcode == 0xe5u) {
|
||||
inst.data_components = inst.data_dwords = 10;
|
||||
if (a16 || d16 || !r128 || inst.dmask != 0xfu ||
|
||||
(nsa_dwords != 0u && nsa_dwords != 2u) || vdata > 246u ||
|
||||
(nsa_dwords == 0u && vaddr > 245u)) {
|
||||
SetUnsupported(inst, Family::MIMG, opcode, "invalid BVH8 ray or destination encoding");
|
||||
}
|
||||
if (nsa_dwords == 2u) {
|
||||
const auto origin = inst.image_nsa_addr[3], direction = inst.image_nsa_addr[4];
|
||||
const auto node = inst.image_nsa_addr[5];
|
||||
if (origin > 253u || direction > 253u)
|
||||
SetUnsupported(inst, Family::MIMG, opcode, "BVH8 ray registers exceed VGPR range");
|
||||
for (uint32_t i = 0; i < 3; ++i) {
|
||||
inst.image_nsa_addr[3 + i] = origin + i;
|
||||
inst.image_nsa_addr[6 + i] = direction + i;
|
||||
}
|
||||
inst.image_nsa_addr[9] = node;
|
||||
}
|
||||
const auto origin = nsa_dwords != 0 ? inst.image_nsa_addr[3] : vaddr + 4;
|
||||
const auto direction = nsa_dwords != 0 ? inst.image_nsa_addr[6] : vaddr + 7;
|
||||
bool overlapping = origin < direction + 3 && direction < origin + 3;
|
||||
for (const auto output : {2u, 3u, 6u, 7u}) {
|
||||
const auto reg = vdata + output;
|
||||
overlapping |= (reg >= origin && reg < origin + 3) ||
|
||||
(reg >= direction && reg < direction + 3);
|
||||
}
|
||||
if (overlapping)
|
||||
SetUnsupported(inst, Family::MIMG, opcode, "overlapping BVH8 instance outputs are unsupported");
|
||||
}
|
||||
|
||||
DecodeVectorGpr(vdata, inst.dst);
|
||||
DecodeVectorGpr(vaddr, inst.src0);
|
||||
DecodeScalarSource(srsrc * 4u, pc, inst.src1);
|
||||
|
||||
@@ -701,6 +701,7 @@ enum class Opcode {
|
||||
DS_WRITE_ADDTID_B32,
|
||||
DS_READ_ADDTID_B32,
|
||||
IMAGE_BVH_INTERSECT_RAY,
|
||||
IMAGE_BVH8_INTERSECT_RAY,
|
||||
IMAGE_GET_RESINFO,
|
||||
IMAGE_GET_LOD,
|
||||
IMAGE_LOAD,
|
||||
|
||||
@@ -326,7 +326,8 @@ IR::Value Translator::MakeImageAddress(const Decoder::Instruction& inst,
|
||||
inst.image_sample_flags, inst.image_dimension, inst.image_address_components);
|
||||
EXIT_IF(count > components.size());
|
||||
const auto nsa_components =
|
||||
std::min(inst.image_nsa_dwords * 4u, Decoder::MaxImageNsaAddressComponents);
|
||||
inst.opcode == Decoder::Opcode::IMAGE_BVH8_INTERSECT_RAY && inst.image_nsa_dwords != 0u
|
||||
? 10u : std::min(inst.image_nsa_dwords * 4u, Decoder::MaxImageNsaAddressComponents);
|
||||
for (uint32_t index = 0; index < count; index++) {
|
||||
if (index != 0u && index - 1u < nsa_components) {
|
||||
components[index] =
|
||||
@@ -948,6 +949,31 @@ void Translator::DS_PERMUTE(const Decoder::Instruction& inst, bool backward) {
|
||||
{ReadU32(inst.src1), address, ir.GetExec()}));
|
||||
}
|
||||
|
||||
void Translator::IMAGE_BVH8(const Decoder::Instruction& inst) {
|
||||
std::array<IR::U32, 10> previous;
|
||||
for (uint32_t i = 0; i < previous.size(); ++i)
|
||||
previous[i] = ReadU32(OffsetOperand(inst.dst, i));
|
||||
const auto result = ir.Emit(IR::ValueOpcode::Bvh8Intersect,
|
||||
{ConstructU32x4(inst.src1, 4), MakeImageAddress(inst, inst.src0), ir.GetExec()});
|
||||
const auto get = [&](uint32_t i) {
|
||||
return IR::U32(ir.Emit(IR::ValueOpcode::Bvh8Extract, {result, IR::Value(i)}));
|
||||
};
|
||||
const auto instance = ir.INotEqual(get(16), IR::U32(IR::Value(0u)));
|
||||
for (uint32_t i = 0; i < 10; ++i) {
|
||||
auto value = get(i);
|
||||
if (i == 0 || i == 1 || i == 4 || i == 5 || i == 8 || i == 9)
|
||||
value = ir.Select(instance, previous[i], value);
|
||||
WriteOperand(OffsetOperand(inst.dst, i), value);
|
||||
}
|
||||
for (uint32_t i = 0; i < 6; ++i) {
|
||||
auto reg = inst.image_nsa_dwords != 0 ? inst.image_nsa_addr[3 + i] : inst.src0.reg + 4 + i;
|
||||
auto target = inst.src0;
|
||||
target.reg = reg;
|
||||
// Non-instance results may alias the ray inputs.
|
||||
WriteOperand(target, ir.Select(instance, get(10 + i), ReadU32(target)));
|
||||
}
|
||||
}
|
||||
|
||||
void Translator::EmitMemory(const Decoder::Instruction& inst) {
|
||||
switch (inst.opcode) {
|
||||
// Translated scalar loads have no cache of their own to invalidate.
|
||||
@@ -956,6 +982,7 @@ void Translator::EmitMemory(const Decoder::Instruction& inst) {
|
||||
case Decoder::Opcode::BUFFER_GL1_INV:
|
||||
ir.Emit(IR::ValueOpcode::DataCacheInvalidate);
|
||||
return;
|
||||
case Decoder::Opcode::IMAGE_BVH8_INTERSECT_RAY: return IMAGE_BVH8(inst);
|
||||
case Decoder::Opcode::IMAGE_BVH_INTERSECT_RAY: {
|
||||
const auto result = ir.Emit(IR::ValueOpcode::BvhIntersect,
|
||||
{ConstructU32x4(inst.src1, 4), MakeImageAddress(inst, inst.src0), ir.GetExec()},
|
||||
|
||||
@@ -105,6 +105,7 @@ private:
|
||||
void WriteSharedU32(uint32_t width, IR::U32 address, const std::array<IR::Value, 4>& values,
|
||||
const IR::MemoryInfo& memory, uint32_t pc);
|
||||
void DS_READ(const Decoder::Instruction& inst);
|
||||
void IMAGE_BVH8(const Decoder::Instruction& inst);
|
||||
void DS_BVH_STACK(const Decoder::Instruction& inst);
|
||||
void DS_READ2(const Decoder::Instruction& inst);
|
||||
void DS_WRITE(const Decoder::Instruction& inst);
|
||||
|
||||
Reference in new issue
Block a user