Files
citra/src/video_core/pica/packed_attribute.h
2023-12-27 23:53:29 +02:00

75 lines
2.3 KiB
C++

// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <boost/serialization/binary_object.hpp>
#include "common/vector_math.h"
#include "video_core/pica_types.h"
namespace Pica {
/**
* Uniforms and fixed attributes are written in a packed format such that four float24 values are
* encoded in three 32-bit numbers. Uniforms can also encode four float32 values in four 32-bit
* numbers. We write to internal memory once a full vector is written.
*/
struct PackedAttribute {
std::array<u32, 4> buffer{};
u32 index{};
/// Places a word to the queue and returns true if the queue becomes full.
constexpr bool Push(u32 word, bool is_float32 = false) {
buffer[index++] = word;
return (index >= 4 && is_float32) || (index >= 3 && !is_float32);
}
/// Resets the queue discarding previous entries.
constexpr void Reset() {
index = 0;
}
/// Returns the queue contents with either float24 or float32 interpretation.
constexpr Common::Vec4<f24> Get(bool is_float32 = false) {
Reset();
if (is_float32) {
return AsFloat32();
} else {
return AsFloat24();
}
}
private:
/// Decodes the queue contents with float24 transfer mode.
constexpr Common::Vec4<f24> AsFloat24() const {
const u32 x = buffer[2] & 0xFFFFFF;
const u32 y = ((buffer[1] & 0xFFFF) << 8) | ((buffer[2] >> 24) & 0xFF);
const u32 z = ((buffer[0] & 0xFF) << 16) | ((buffer[1] >> 16) & 0xFFFF);
const u32 w = buffer[0] >> 8;
return Common::Vec4<f24>{f24::FromRaw(x), f24::FromRaw(y), f24::FromRaw(z),
f24::FromRaw(w)};
}
/// Decodes the queue contents with float32 transfer mode.
constexpr Common::Vec4<f24> AsFloat32() const {
Common::Vec4<f24> uniform;
for (u32 i = 0; i < 4; i++) {
const f32 buffer_value = std::bit_cast<f32>(buffer[i]);
uniform[3 - i] = f24::FromFloat32(buffer_value);
}
return uniform;
}
private:
template <class Archive>
void serialize(Archive& ar, const u32) {
ar& buffer;
ar& index;
}
friend class boost::serialization::access;
};
} // namespace Pica