mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-22 03:46:53 +02:00
shader: fix packed image address reads
This commit is contained in:
@@ -274,6 +274,7 @@ uint32_t DecodeMimgAddressComponents(uint32_t opcode, ImageDimension dimension,
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case 0x0eu: return 1u;
|
||||
case 0x01u:
|
||||
case 0x09u: return ImageCoordComponents(dimension) + 1u;
|
||||
case 0x00u:
|
||||
@@ -297,6 +298,36 @@ bool IsSingleDmaskBit(uint32_t dmask) {
|
||||
|
||||
} // namespace
|
||||
|
||||
ImageAddressComponent ImageAddressComponentLayout(uint32_t flags, uint32_t component) {
|
||||
const auto width = [flags](uint32_t index) {
|
||||
if ((flags & ImageSampleFlagA16) == 0u) return 32u;
|
||||
uint32_t cursor = 0;
|
||||
if ((flags & ImageSampleFlagOffset) != 0u) {
|
||||
if (index == cursor++) return 32u;
|
||||
}
|
||||
if ((flags & ImageSampleFlagBias) != 0u) {
|
||||
if (index == cursor++) return 16u;
|
||||
}
|
||||
if ((flags & ImageSampleFlagCompare) != 0u && index == cursor) return 32u;
|
||||
return 16u;
|
||||
};
|
||||
uint32_t offset = 0;
|
||||
for (uint32_t index = 0; index < component; index++) {
|
||||
const auto bits = width(index);
|
||||
if (bits == 32u) offset = (offset + 31u) & ~31u;
|
||||
offset += bits;
|
||||
}
|
||||
const auto bits = width(component);
|
||||
if (bits == 32u) offset = (offset + 31u) & ~31u;
|
||||
return {offset, bits};
|
||||
}
|
||||
|
||||
uint32_t ImageAddressDwordCount(uint32_t flags, uint32_t components) {
|
||||
if (components == 0u) return 0u;
|
||||
const auto last = ImageAddressComponentLayout(flags, components - 1u);
|
||||
return (last.bit_offset + last.bit_width + 31u) / 32u;
|
||||
}
|
||||
|
||||
void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
Instruction& inst) {
|
||||
const uint32_t word0 = code[word_index];
|
||||
|
||||
@@ -10,6 +10,14 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
|
||||
const char* MimgSampleOpcodeName(uint32_t opcode);
|
||||
|
||||
struct ImageAddressComponent {
|
||||
uint32_t bit_offset;
|
||||
uint32_t bit_width;
|
||||
};
|
||||
|
||||
ImageAddressComponent ImageAddressComponentLayout(uint32_t flags, uint32_t component);
|
||||
uint32_t ImageAddressDwordCount(uint32_t flags, uint32_t components);
|
||||
|
||||
} // namespace Libs::Graphics::ShaderRecompiler::Decoder
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_IMAGEOPS_H_ */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "graphics/shader/recompiler/frontend/translate/Translator.h"
|
||||
#include "graphics/shader/recompiler/frontend/decode/ImageOps.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -330,11 +331,14 @@ IR::Value Translator::MakeImageAddress(const Decoder::Instruction& inst,
|
||||
const Decoder::Operand& base) {
|
||||
const auto memory = MemoryInfoFromDecoded(inst);
|
||||
std::array<IR::Value, 13> components {};
|
||||
components[0] = ReadRawU32(PlainOperand(base));
|
||||
components.fill(IR::Value(0u));
|
||||
const auto count =
|
||||
Decoder::ImageAddressDwordCount(memory.image_sample_flags, memory.image_address_components);
|
||||
EXIT_IF(count > components.size());
|
||||
const auto nsa_components =
|
||||
std::min(memory.image_nsa_dwords * 4u, Decoder::MaxImageNsaAddressComponents);
|
||||
for (uint32_t index = 1; index < components.size(); index++) {
|
||||
if (index - 1u < nsa_components) {
|
||||
for (uint32_t index = 0; index < count; index++) {
|
||||
if (index != 0u && index - 1u < nsa_components) {
|
||||
components[index] =
|
||||
ir.GetVectorReg(static_cast<IR::VectorReg>(memory.image_nsa_addr[index - 1u]));
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user