[Code] Make union usage more consistent

This commit is contained in:
Triang3l 2021-11-01 22:56:24 +03:00 committed by Triang3l
parent dbd518f137
commit fdec0ab332
18 changed files with 148 additions and 125 deletions

View File

@ -46,6 +46,7 @@ enum KeyType {
#pragma pack(push, 1)
union InstrKey {
uint32_t value;
struct {
uint32_t opcode : 8;
uint32_t dest : 5;
@ -54,11 +55,10 @@ union InstrKey {
uint32_t src3 : 5;
uint32_t reserved : 4;
};
uint32_t value;
operator uint32_t() const { return value; }
InstrKey() : value(0) {}
InstrKey() : value(0) { static_assert_size(*this, sizeof(value)); }
InstrKey(uint32_t v) : value(v) {}
InstrKey(const Instr* i) : value(0) {
opcode = i->opcode->num;

View File

@ -67,34 +67,34 @@ enum class GammaRampType {
struct GammaRamp {
struct NormalEntry {
union {
uint32_t value;
struct {
uint32_t b : 10;
uint32_t g : 10;
uint32_t r : 10;
uint32_t : 2;
};
uint32_t value;
};
};
struct PWLValue {
union {
uint32_t value;
struct {
uint16_t base;
uint16_t delta;
};
uint32_t value;
};
};
struct PWLEntry {
union {
PWLValue values[3];
struct {
PWLValue r;
PWLValue g;
PWLValue b;
};
PWLValue values[3];
};
};

View File

@ -410,6 +410,7 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
static const TransferModeInfo kTransferModes[size_t(TransferMode::kCount)];
union TransferShaderKey {
uint32_t key;
struct {
xenos::MsaaSamples dest_msaa_samples : xenos::kMsaaSamplesBits;
uint32_t dest_resource_format : xenos::kRenderTargetFormatBits;
@ -433,7 +434,9 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
static_assert(size_t(TransferMode::kCount) <= (size_t(1) << 3));
TransferMode mode : 3;
};
uint32_t key = 0;
TransferShaderKey() : key(0) { static_assert_size(*this, sizeof(key)); }
struct Hasher {
size_t operator()(const TransferShaderKey& key) const {
return std::hash<uint32_t>{}(key.key);
@ -451,6 +454,7 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
};
union TransferAddressConstant {
uint32_t constant;
struct {
// All in tiles.
uint32_t dest_pitch : xenos::kEdramPitchTilesBits;
@ -466,7 +470,9 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
// destination == source anyway).
int32_t source_to_dest : xenos::kEdramBaseTilesBits;
};
uint32_t constant = 0;
TransferAddressConstant() : constant(0) {
static_assert_size(*this, sizeof(constant));
}
bool operator==(const TransferAddressConstant& other_constant) const {
return constant == other_constant.constant;
}
@ -474,7 +480,6 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
return !(*this == other_constant);
}
};
static_assert(sizeof(TransferAddressConstant) == sizeof(uint32_t));
struct TransferInvocation {
Transfer transfer;
@ -515,6 +520,7 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
};
union HostDepthStoreRectangleConstant {
uint32_t constant;
struct {
// - 1 because the maximum is 0x1FFF / 8, not 0x2000 / 8.
uint32_t x_pixels_div_8 : xenos::kResolveSizeBits - 1 -
@ -524,11 +530,13 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
uint32_t width_pixels_div_8_minus_1 : xenos::kResolveSizeBits - 1 -
xenos::kResolveAlignmentPixelsLog2;
};
uint32_t constant = 0;
HostDepthStoreRectangleConstant() : constant(0) {
static_assert_size(*this, sizeof(constant));
}
};
static_assert(sizeof(HostDepthStoreRectangleConstant) == sizeof(uint32_t));
union HostDepthStoreRenderTargetConstant {
uint32_t constant;
struct {
uint32_t pitch_tiles : xenos::kEdramPitchTilesBits;
// 1 to 3.
@ -536,9 +544,10 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
// Whether 2x MSAA is supported natively rather than through 4x.
uint32_t msaa_2x_supported : 1;
};
uint32_t constant = 0;
HostDepthStoreRenderTargetConstant() : constant(0) {
static_assert_size(*this, sizeof(constant));
}
};
static_assert(sizeof(HostDepthStoreRenderTargetConstant) == sizeof(uint32_t));
enum {
kHostDepthStoreRootParameterRectangleConstant,
@ -549,6 +558,7 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
};
union DumpPipelineKey {
uint32_t key;
struct {
xenos::MsaaSamples msaa_samples : 2;
uint32_t resource_format : 4;
@ -556,7 +566,9 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
// change it at most once. Depth buffers have an additional stencil SRV.
uint32_t is_depth : 1;
};
uint32_t key = 0;
DumpPipelineKey() : key(0) { static_assert_size(*this, sizeof(key)); }
struct Hasher {
size_t operator()(const DumpPipelineKey& key) const {
return std::hash<uint32_t>{}(key.key);
@ -583,13 +595,14 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
};
union DumpOffsets {
uint32_t offsets;
struct {
// Absolute index of the first thread group's tile within the source
// texture.
uint32_t first_group_tile_source_relative : xenos::kEdramBaseTilesBits;
uint32_t source_base_tiles : xenos::kEdramBaseTilesBits;
};
uint32_t offsets = 0;
DumpOffsets() : offsets(0) { static_assert_size(*this, sizeof(offsets)); }
bool operator==(const DumpOffsets& other_offsets) const {
return offsets == other_offsets.offsets;
}
@ -597,15 +610,15 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
return !(*this == other_offsets);
}
};
static_assert(sizeof(DumpOffsets) == sizeof(uint32_t));
union DumpPitches {
uint32_t pitches;
struct {
// Both in tiles.
uint32_t source_pitch : xenos::kEdramPitchTilesBits;
uint32_t dest_pitch : xenos::kEdramPitchTilesBits;
};
uint32_t pitches = 0;
DumpPitches() : pitches(0) { static_assert_size(*this, sizeof(pitches)); }
bool operator==(const DumpPitches& other_pitches) const {
return pitches == other_pitches.pitches;
}
@ -613,7 +626,6 @@ class D3D12RenderTargetCache final : public RenderTargetCache {
return !(*this == other_pitches);
}
};
static_assert(sizeof(DumpPitches) == sizeof(uint32_t));
enum DumpCbuffer : uint32_t {
kDumpCbufferOffsets,

View File

@ -124,6 +124,7 @@ class TextureCache {
// Sampler parameters that can be directly converted to a host sampler or used
// for binding checking validity whether samplers are up to date.
union SamplerParameters {
uint32_t value;
struct {
xenos::ClampMode clamp_x : 3; // 3
xenos::ClampMode clamp_y : 3; // 6
@ -137,16 +138,8 @@ class TextureCache {
uint32_t mip_min_level : 4; // 21
// Maximum mip level is in the texture resource itself.
};
uint32_t value;
// Clearing the unused bits.
SamplerParameters() : value(0) {}
SamplerParameters(const SamplerParameters& parameters)
: value(parameters.value) {}
SamplerParameters& operator=(const SamplerParameters& parameters) {
value = parameters.value;
return *this;
}
SamplerParameters() : value(0) { static_assert_size(*this, sizeof(value)); }
bool operator==(const SamplerParameters& parameters) const {
return value == parameters.value;
}

View File

@ -215,6 +215,7 @@ xenos::CopySampleSelect SanitizeCopySampleSelect(
// constants.
union ResolveEdramPackedInfo {
uint32_t packed;
struct {
// With 32bpp/64bpp taken into account.
uint32_t pitch_tiles : xenos::kEdramPitchTilesBits;
@ -228,12 +229,15 @@ union ResolveEdramPackedInfo {
// the impact of the half-pixel offset with resolution scaling.
uint32_t duplicate_second_pixel : 1;
};
uint32_t packed;
ResolveEdramPackedInfo() : packed(0) {
static_assert_size(*this, sizeof(packed));
}
};
static_assert(sizeof(ResolveEdramPackedInfo) <= sizeof(uint32_t),
"ResolveEdramPackedInfo must be packable in uint32_t");
union ResolveAddressPackedInfo {
uint32_t packed;
struct {
// 160x32 is divisible by both the EDRAM tile size (80x16 samples, but for
// simplicity, this is in pixels) and the texture tile size (32x32), so
@ -258,7 +262,9 @@ union ResolveAddressPackedInfo {
xenos::CopySampleSelect copy_sample_select : 3;
};
uint32_t packed;
ResolveAddressPackedInfo() : packed(0) {
static_assert_size(*this, sizeof(packed));
}
};
static_assert(sizeof(ResolveAddressPackedInfo) <= sizeof(uint32_t),
"ResolveAddressPackedInfo must be packable in uint32_t");
@ -271,6 +277,7 @@ void GetResolveEdramTileSpan(ResolveEdramPackedInfo edram_info,
uint32_t& rows_out);
union ResolveCopyDestPitchPackedInfo {
uint32_t packed;
struct {
// 0...16384/32.
uint32_t pitch_aligned_div_32 : xenos::kTexture2DCubeMaxWidthHeightLog2 +
@ -278,10 +285,10 @@ union ResolveCopyDestPitchPackedInfo {
uint32_t height_aligned_div_32 : xenos::kTexture2DCubeMaxWidthHeightLog2 +
2 - xenos::kTextureTileWidthHeightLog2;
};
uint32_t packed;
ResolveCopyDestPitchPackedInfo() : packed(0) {
static_assert_size(*this, sizeof(packed));
}
};
static_assert(sizeof(ResolveCopyDestPitchPackedInfo) <= sizeof(uint32_t),
"ResolveAddressPackedInfo must be packable in uint32_t");
// For backends with Shader Model 5-like compute, host shaders to use to perform
// copying in resolve operations.

View File

@ -15,6 +15,7 @@
#include <string>
#include <vector>
#include "xenia/base/assert.h"
#include "xenia/base/math.h"
#include "xenia/base/string_buffer.h"
#include "xenia/gpu/dxbc.h"
@ -85,6 +86,7 @@ class DxbcShaderTranslator : public ShaderTranslator {
kFloat24Rounding,
};
uint64_t value;
struct VertexShaderModification {
// Dynamically indexable register count from SQ_PROGRAM_CNTL.
uint32_t dynamic_addressable_register_count : 8;
@ -98,9 +100,10 @@ class DxbcShaderTranslator : public ShaderTranslator {
// Non-ROV - depth / stencil output mode.
DepthStencilMode depth_stencil_mode : 2;
} pixel;
uint64_t value = 0;
Modification(uint64_t modification_value = 0) : value(modification_value) {}
Modification(uint64_t modification_value = 0) : value(modification_value) {
static_assert_size(*this, sizeof(value));
}
};
// Constant buffer bindings in space 0.

View File

@ -685,6 +685,7 @@ class PrimitiveProcessor {
kCacheBucketSizeBytes;
union CacheKey {
uint64_t key;
struct {
uint32_t base; // 32 total
uint32_t count : 16; // 48
@ -694,19 +695,23 @@ class PrimitiveProcessor {
// kNone if not changing the type (like only processing the reset index).
xenos::PrimitiveType conversion_guest_primitive_type : 6; // 59
};
uint64_t key = 0;
CacheKey() = default;
CacheKey() : key(0) { static_assert_size(*this, sizeof(key)); }
CacheKey(uint32_t base, uint32_t count, xenos::IndexFormat format,
xenos::Endian endian, bool is_reset_enabled,
xenos::PrimitiveType conversion_guest_primitive_type =
xenos::PrimitiveType::kNone)
: base(base),
count(count),
format(format),
endian(endian),
is_reset_enabled(is_reset_enabled),
conversion_guest_primitive_type(conversion_guest_primitive_type) {}
xenos::PrimitiveType::kNone) {
// Clear unused bits, then set each field explicitly, not via the
// initializer list (which causes `uint64_t key = 0;` to be ignored, and
// also can't contain initializers for aliasing union members).
key = 0;
this->base = base;
this->count = count;
this->format = format;
this->endian = endian;
this->is_reset_enabled = is_reset_enabled;
this->conversion_guest_primitive_type = conversion_guest_primitive_type;
}
struct Hasher {
size_t operator()(const CacheKey& key) const {

View File

@ -46,6 +46,7 @@ namespace reg {
*******************************************************************************/
union alignas(uint32_t) COHER_STATUS_HOST {
uint32_t value;
struct {
uint32_t matching_contexts : 8; // +0
uint32_t rb_copy_dest_base_ena : 1; // +8
@ -64,12 +65,12 @@ union alignas(uint32_t) COHER_STATUS_HOST {
uint32_t : 4; // +27
uint32_t status : 1; // +31
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_COHER_STATUS_HOST;
};
static_assert_size(COHER_STATUS_HOST, sizeof(uint32_t));
union alignas(uint32_t) WAIT_UNTIL {
uint32_t value;
struct {
uint32_t : 1; // +0
uint32_t wait_re_vsync : 1; // +1
@ -88,7 +89,6 @@ union alignas(uint32_t) WAIT_UNTIL {
uint32_t : 2; // +18
uint32_t cmdfifo_entries : 4; // +20
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_WAIT_UNTIL;
};
static_assert_size(WAIT_UNTIL, sizeof(uint32_t));
@ -102,6 +102,7 @@ static_assert_size(WAIT_UNTIL, sizeof(uint32_t));
*******************************************************************************/
union alignas(uint32_t) SQ_PROGRAM_CNTL {
uint32_t value;
struct {
// Note from a2xx.xml:
// Only 0x3F worth of valid register values for VS_NUM_REG and PS_NUM_REG,
@ -118,12 +119,12 @@ union alignas(uint32_t) SQ_PROGRAM_CNTL {
uint32_t ps_export_mode : 4; // +27
uint32_t gen_index_vtx : 1; // +31
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_SQ_PROGRAM_CNTL;
};
static_assert_size(SQ_PROGRAM_CNTL, sizeof(uint32_t));
union alignas(uint32_t) SQ_CONTEXT_MISC {
uint32_t value;
struct {
uint32_t inst_pred_optimize : 1; // +0
uint32_t sc_output_screen_xy : 1; // +1
@ -150,19 +151,18 @@ union alignas(uint32_t) SQ_CONTEXT_MISC {
uint32_t yeild_optimize : 1; // +17 sic
uint32_t tx_cache_sel : 1; // +18
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_SQ_CONTEXT_MISC;
};
static_assert_size(SQ_CONTEXT_MISC, sizeof(uint32_t));
union alignas(uint32_t) SQ_INTERPOLATOR_CNTL {
uint32_t value;
struct {
uint32_t param_shade : 16; // +0
// SampleLocation bits - 0 for centroid, 1 for center, if
// SQ_CONTEXT_MISC::sc_sample_cntl is kCentroidsAndCenters.
uint32_t sampling_pattern : 16; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_SQ_INTERPOLATOR_CNTL;
};
static_assert_size(SQ_INTERPOLATOR_CNTL, sizeof(uint32_t));
@ -186,16 +186,17 @@ static_assert_size(SQ_INTERPOLATOR_CNTL, sizeof(uint32_t));
*******************************************************************************/
union alignas(uint32_t) VGT_DMA_SIZE {
uint32_t value;
struct {
uint32_t num_words : 24; // +0
uint32_t : 6; // +24
xenos::Endian swap_mode : 2; // +30
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_VGT_DMA_SIZE;
};
union alignas(uint32_t) VGT_DRAW_INITIATOR {
uint32_t value;
// Different than on A2xx and R6xx/R7xx.
struct {
xenos::PrimitiveType prim_type : 6; // +0
@ -207,7 +208,6 @@ union alignas(uint32_t) VGT_DRAW_INITIATOR {
uint32_t : 3; // +13
uint32_t num_indices : 16; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_VGT_DRAW_INITIATOR;
};
static_assert_size(VGT_DRAW_INITIATOR, sizeof(uint32_t));
@ -223,6 +223,7 @@ static_assert_size(VGT_DRAW_INITIATOR, sizeof(uint32_t));
// clamping.
union alignas(uint32_t) VGT_MULTI_PRIM_IB_RESET_INDX {
uint32_t value;
struct {
// The upper 8 bits of the value from the index buffer are confirmed to be
// ignored. So, though this specifically is untested (because
@ -234,13 +235,13 @@ union alignas(uint32_t) VGT_MULTI_PRIM_IB_RESET_INDX {
// 0x1FFFFFF, 0xFFFFFFFF all cause primitive reset.
uint32_t reset_indx : 24;
};
uint32_t value;
static constexpr Register register_index =
XE_GPU_REG_VGT_MULTI_PRIM_IB_RESET_INDX;
};
static_assert_size(VGT_MULTI_PRIM_IB_RESET_INDX, sizeof(uint32_t));
union alignas(uint32_t) VGT_INDX_OFFSET {
uint32_t value;
struct {
// Unlike R5xx's VAP_INDEX_OFFSET, which is signed 25-bit, this is 24-bit -
// and signedness doesn't matter as index calculations are done in 24-bit
@ -251,44 +252,43 @@ union alignas(uint32_t) VGT_INDX_OFFSET {
// anyway, and that has no effect on offsets that fit in 24 bits.
uint32_t indx_offset : 24;
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_VGT_INDX_OFFSET;
};
static_assert_size(VGT_INDX_OFFSET, sizeof(uint32_t));
union alignas(uint32_t) VGT_MIN_VTX_INDX {
uint32_t value;
struct {
uint32_t min_indx : 24;
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_VGT_MIN_VTX_INDX;
};
static_assert_size(VGT_MIN_VTX_INDX, sizeof(uint32_t));
union alignas(uint32_t) VGT_MAX_VTX_INDX {
uint32_t value;
struct {
// Usually 0xFFFF or 0xFFFFFF.
uint32_t max_indx : 24;
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_VGT_MAX_VTX_INDX;
};
static_assert_size(VGT_MAX_VTX_INDX, sizeof(uint32_t));
union alignas(uint32_t) VGT_OUTPUT_PATH_CNTL {
uint32_t value;
struct {
xenos::VGTOutputPath path_select : 2; // +0
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_VGT_OUTPUT_PATH_CNTL;
};
static_assert_size(VGT_OUTPUT_PATH_CNTL, sizeof(uint32_t));
union alignas(uint32_t) VGT_HOS_CNTL {
uint32_t value;
struct {
xenos::TessellationMode tess_mode : 2; // +0
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_VGT_HOS_CNTL;
};
static_assert_size(VGT_HOS_CNTL, sizeof(uint32_t));
@ -307,29 +307,30 @@ static_assert_size(VGT_HOS_CNTL, sizeof(uint32_t));
*******************************************************************************/
union alignas(uint32_t) PA_SU_POINT_MINMAX {
uint32_t value;
struct {
// Radius, 12.4 fixed point.
uint32_t min_size : 16; // +0
uint32_t max_size : 16; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SU_POINT_MINMAX;
};
static_assert_size(PA_SU_POINT_MINMAX, sizeof(uint32_t));
union alignas(uint32_t) PA_SU_POINT_SIZE {
uint32_t value;
struct {
// 1/2 width or height, 12.4 fixed point.
uint32_t height : 16; // +0
uint32_t width : 16; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SU_POINT_SIZE;
};
static_assert_size(PA_SU_POINT_SIZE, sizeof(uint32_t));
// Setup Unit / Scanline Converter mode cntl
union alignas(uint32_t) PA_SU_SC_MODE_CNTL {
uint32_t value;
struct {
uint32_t cull_front : 1; // +0
uint32_t cull_back : 1; // +1
@ -359,36 +360,36 @@ union alignas(uint32_t) PA_SU_SC_MODE_CNTL {
// WAIT_RB_IDLE_ALL_TRI and WAIT_RB_IDLE_FIRST_TRI_NEW_STATE were added on
// Adreno.
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SU_SC_MODE_CNTL;
};
static_assert_size(PA_SU_SC_MODE_CNTL, sizeof(uint32_t));
// Setup Unit Vertex Control
union alignas(uint32_t) PA_SU_VTX_CNTL {
uint32_t value;
struct {
uint32_t pix_center : 1; // +0 1 = half pixel offset (OpenGL).
uint32_t round_mode : 2; // +1
uint32_t quant_mode : 3; // +3
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SU_VTX_CNTL;
};
static_assert_size(PA_SU_VTX_CNTL, sizeof(uint32_t));
union alignas(uint32_t) PA_SC_MPASS_PS_CNTL {
uint32_t value;
struct {
uint32_t mpass_pix_vec_per_pass : 20; // +0
uint32_t : 11; // +20
uint32_t mpass_ps_ena : 1; // +31
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SC_MPASS_PS_CNTL;
};
static_assert_size(PA_SC_MPASS_PS_CNTL, sizeof(uint32_t));
// Scanline converter viz query, used by D3D for gpu side conditional rendering
union alignas(uint32_t) PA_SC_VIZ_QUERY {
uint32_t value;
struct {
// the visibility of draws should be evaluated
uint32_t viz_query_ena : 1; // +0
@ -398,13 +399,13 @@ union alignas(uint32_t) PA_SC_VIZ_QUERY {
// not used with d3d
uint32_t kill_pix_post_detail_mask : 1; // +8
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SC_VIZ_QUERY;
};
static_assert_size(PA_SC_VIZ_QUERY, sizeof(uint32_t));
// Clipper clip control
union alignas(uint32_t) PA_CL_CLIP_CNTL {
uint32_t value;
struct {
uint32_t ucp_ena_0 : 1; // +0
uint32_t ucp_ena_1 : 1; // +1
@ -424,13 +425,13 @@ union alignas(uint32_t) PA_CL_CLIP_CNTL {
uint32_t z_nan_retain : 1; // +23
uint32_t w_nan_retain : 1; // +24
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_CL_CLIP_CNTL;
};
static_assert_size(PA_CL_CLIP_CNTL, sizeof(uint32_t));
// Viewport transform engine control
union alignas(uint32_t) PA_CL_VTE_CNTL {
uint32_t value;
struct {
uint32_t vport_x_scale_ena : 1; // +0
uint32_t vport_x_offset_ena : 1; // +1
@ -444,45 +445,45 @@ union alignas(uint32_t) PA_CL_VTE_CNTL {
uint32_t vtx_w0_fmt : 1; // +10
uint32_t perfcounter_ref : 1; // +11
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_CL_VTE_CNTL;
};
static_assert_size(PA_CL_VTE_CNTL, sizeof(uint32_t));
union alignas(uint32_t) PA_SC_SCREEN_SCISSOR_TL {
uint32_t value;
struct {
int32_t tl_x : 15; // +0
uint32_t : 1; // +15
int32_t tl_y : 15; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SC_SCREEN_SCISSOR_TL;
};
static_assert_size(PA_SC_SCREEN_SCISSOR_TL, sizeof(uint32_t));
union alignas(uint32_t) PA_SC_SCREEN_SCISSOR_BR {
uint32_t value;
struct {
int32_t br_x : 15; // +0
uint32_t : 1; // +15
int32_t br_y : 15; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SC_SCREEN_SCISSOR_BR;
};
static_assert_size(PA_SC_SCREEN_SCISSOR_BR, sizeof(uint32_t));
union alignas(uint32_t) PA_SC_WINDOW_OFFSET {
uint32_t value;
struct {
int32_t window_x_offset : 15; // +0
uint32_t : 1; // +15
int32_t window_y_offset : 15; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SC_WINDOW_OFFSET;
};
static_assert_size(PA_SC_WINDOW_OFFSET, sizeof(uint32_t));
union alignas(uint32_t) PA_SC_WINDOW_SCISSOR_TL {
uint32_t value;
struct {
uint32_t tl_x : 14; // +0
uint32_t : 2; // +14
@ -490,18 +491,17 @@ union alignas(uint32_t) PA_SC_WINDOW_SCISSOR_TL {
uint32_t : 1; // +30
uint32_t window_offset_disable : 1; // +31
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SC_WINDOW_SCISSOR_TL;
};
static_assert_size(PA_SC_WINDOW_SCISSOR_TL, sizeof(uint32_t));
union alignas(uint32_t) PA_SC_WINDOW_SCISSOR_BR {
uint32_t value;
struct {
uint32_t br_x : 14; // +0
uint32_t : 2; // +14
uint32_t br_y : 14; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_PA_SC_WINDOW_SCISSOR_BR;
};
static_assert_size(PA_SC_WINDOW_SCISSOR_BR, sizeof(uint32_t));
@ -520,27 +520,28 @@ static_assert_size(PA_SC_WINDOW_SCISSOR_BR, sizeof(uint32_t));
*******************************************************************************/
union alignas(uint32_t) RB_MODECONTROL {
uint32_t value;
struct {
xenos::ModeControl edram_mode : 3; // +0
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_MODECONTROL;
};
static_assert_size(RB_MODECONTROL, sizeof(uint32_t));
union alignas(uint32_t) RB_SURFACE_INFO {
uint32_t value;
struct {
uint32_t surface_pitch : 14; // +0 in pixels.
uint32_t : 2; // +14
xenos::MsaaSamples msaa_samples : 2; // +16
uint32_t hiz_pitch : 14; // +18
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_SURFACE_INFO;
};
static_assert_size(RB_SURFACE_INFO, sizeof(uint32_t));
union alignas(uint32_t) RB_COLORCONTROL {
uint32_t value;
struct {
xenos::CompareFunction alpha_func : 3; // +0
uint32_t alpha_test_enable : 1; // +3
@ -585,19 +586,18 @@ union alignas(uint32_t) RB_COLORCONTROL {
uint32_t alpha_to_mask_offset2 : 2; // +28
uint32_t alpha_to_mask_offset3 : 2; // +30
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_COLORCONTROL;
};
static_assert_size(RB_COLORCONTROL, sizeof(uint32_t));
union alignas(uint32_t) RB_COLOR_INFO {
uint32_t value;
struct {
uint32_t color_base : 12; // +0 in tiles.
uint32_t : 4; // +12
xenos::ColorRenderTargetFormat color_format : 4; // +16
int32_t color_exp_bias : 6; // +20
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_COLOR_INFO;
// RB_COLOR[1-3]_INFO also use this format.
static const Register rt_register_indices[4];
@ -605,6 +605,7 @@ union alignas(uint32_t) RB_COLOR_INFO {
static_assert_size(RB_COLOR_INFO, sizeof(uint32_t));
union alignas(uint32_t) RB_COLOR_MASK {
uint32_t value;
struct {
uint32_t write_red0 : 1; // +0
uint32_t write_green0 : 1; // +1
@ -623,12 +624,12 @@ union alignas(uint32_t) RB_COLOR_MASK {
uint32_t write_blue3 : 1; // +14
uint32_t write_alpha3 : 1; // +15
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_COLOR_MASK;
};
static_assert_size(RB_COLOR_MASK, sizeof(uint32_t));
union alignas(uint32_t) RB_BLENDCONTROL {
uint32_t value;
struct {
xenos::BlendFactor color_srcblend : 5; // +0
xenos::BlendOp color_comb_fcn : 3; // +5
@ -639,7 +640,6 @@ union alignas(uint32_t) RB_BLENDCONTROL {
xenos::BlendFactor alpha_destblend : 5; // +24
// BLEND_FORCE_ENABLE and BLEND_FORCE were added on Adreno.
};
uint32_t value;
// RB_BLENDCONTROL[0-3] use this format.
static constexpr Register register_index = XE_GPU_REG_RB_BLENDCONTROL0;
static const Register rt_register_indices[4];
@ -647,6 +647,7 @@ union alignas(uint32_t) RB_BLENDCONTROL {
static_assert_size(RB_BLENDCONTROL, sizeof(uint32_t));
union alignas(uint32_t) RB_DEPTHCONTROL {
uint32_t value;
struct {
uint32_t stencil_enable : 1; // +0
uint32_t z_enable : 1; // +1
@ -664,30 +665,29 @@ union alignas(uint32_t) RB_DEPTHCONTROL {
xenos::StencilOp stencilzpass_bf : 3; // +26
xenos::StencilOp stencilzfail_bf : 3; // +29
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_DEPTHCONTROL;
};
static_assert_size(RB_DEPTHCONTROL, sizeof(uint32_t));
union alignas(uint32_t) RB_STENCILREFMASK {
uint32_t value;
struct {
uint32_t stencilref : 8; // +0
uint32_t stencilmask : 8; // +8
uint32_t stencilwritemask : 8; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_STENCILREFMASK;
// RB_STENCILREFMASK_BF also uses this format.
};
static_assert_size(RB_STENCILREFMASK, sizeof(uint32_t));
union alignas(uint32_t) RB_DEPTH_INFO {
uint32_t value;
struct {
uint32_t depth_base : 12; // +0 in tiles.
uint32_t : 4; // +12
xenos::DepthRenderTargetFormat depth_format : 1; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_DEPTH_INFO;
};
static_assert_size(RB_DEPTH_INFO, sizeof(uint32_t));
@ -695,6 +695,7 @@ static_assert_size(RB_DEPTH_INFO, sizeof(uint32_t));
// Copy registers are very different than on Adreno.
union alignas(uint32_t) RB_COPY_CONTROL {
uint32_t value;
struct {
uint32_t copy_src_select : 3; // +0 Depth is 4.
uint32_t : 1; // +3
@ -705,12 +706,12 @@ union alignas(uint32_t) RB_COPY_CONTROL {
uint32_t : 10; // +10
xenos::CopyCommand copy_command : 2; // +20
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_COPY_CONTROL;
};
static_assert_size(RB_COPY_CONTROL, sizeof(uint32_t));
union alignas(uint32_t) RB_COPY_DEST_INFO {
uint32_t value;
struct {
xenos::Endian128 copy_dest_endian : 3; // +0
uint32_t copy_dest_array : 1; // +3
@ -721,18 +722,17 @@ union alignas(uint32_t) RB_COPY_DEST_INFO {
uint32_t : 2; // +22
uint32_t copy_dest_swap : 1; // +24
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_COPY_DEST_INFO;
};
static_assert_size(RB_COPY_DEST_INFO, sizeof(uint32_t));
union alignas(uint32_t) RB_COPY_DEST_PITCH {
uint32_t value;
struct {
uint32_t copy_dest_pitch : 14; // +0
uint32_t : 2; // +14
uint32_t copy_dest_height : 14; // +16
};
uint32_t value;
static constexpr Register register_index = XE_GPU_REG_RB_COPY_DEST_PITCH;
};
static_assert_size(RB_COPY_DEST_PITCH, sizeof(uint32_t));

View File

@ -217,6 +217,7 @@ class RenderTargetCache {
// rest of the EDRAM is transferred.
union RenderTargetKey {
uint32_t key;
struct {
// [0, 2047].
uint32_t base_tiles : xenos::kEdramBaseTilesBits - 1; // 11
@ -228,7 +229,9 @@ class RenderTargetCache {
// Ignoring the blending precision and sRGB.
uint32_t resource_format : xenos::kRenderTargetFormatBits; // 26
};
uint32_t key = 0;
RenderTargetKey() : key(0) { static_assert_size(*this, sizeof(key)); }
struct Hasher {
size_t operator()(const RenderTargetKey& render_target_key) const {
return std::hash<uint32_t>{}(render_target_key.key);

View File

@ -422,15 +422,15 @@ union ControlFlowInstruction {
ControlFlowCondJmpInstruction cond_jmp; // kCondJmp
ControlFlowAllocInstruction alloc; // kAlloc
struct {
uint32_t dword_0;
uint32_t dword_1;
};
struct {
uint32_t unused_0 : 32;
uint32_t unused_1 : 12;
ControlFlowOpcode opcode_value : 4;
};
struct {
uint32_t dword_0;
uint32_t dword_1;
};
};
static_assert_size(ControlFlowInstruction, sizeof(uint32_t) * 2);

View File

@ -65,6 +65,7 @@ class TextureCache {
VkImageView view;
union {
uint16_t swizzle;
struct {
// FIXME: This only applies on little-endian platforms!
uint16_t swiz_x : 3;
@ -73,8 +74,6 @@ class TextureCache {
uint16_t swiz_w : 3;
uint16_t : 4;
};
uint16_t swizzle;
};
};

View File

@ -985,6 +985,10 @@ enum class FetchConstantType : uint32_t {
// XE_GPU_REG_SHADER_CONSTANT_FETCH_*
union alignas(uint32_t) xe_gpu_vertex_fetch_t {
struct {
uint32_t dword_0;
uint32_t dword_1;
};
struct {
FetchConstantType type : 2; // +0
uint32_t address : 30; // +2 address in dwords
@ -993,10 +997,6 @@ union alignas(uint32_t) xe_gpu_vertex_fetch_t {
uint32_t size : 24; // +2 size in words
uint32_t unk1 : 6; // +26
};
struct {
uint32_t dword_0;
uint32_t dword_1;
};
};
static_assert_size(xe_gpu_vertex_fetch_t, sizeof(uint32_t) * 2);
@ -1044,6 +1044,14 @@ constexpr uint32_t kTextureLinearRowAlignmentBytes =
// XE_GPU_REG_SHADER_CONSTANT_FETCH_*
union alignas(uint32_t) xe_gpu_texture_fetch_t {
struct {
uint32_t dword_0;
uint32_t dword_1;
uint32_t dword_2;
uint32_t dword_3;
uint32_t dword_4;
uint32_t dword_5;
};
struct {
FetchConstantType type : 2; // +0 dword_0
// Likely before the swizzle, seems logical from R5xx (SIGNED_COMP0/1/2/3
@ -1135,25 +1143,11 @@ union alignas(uint32_t) xe_gpu_texture_fetch_t {
uint32_t packed_mips : 1; // +11
uint32_t mip_address : 20; // +12 mip address >> 12
};
struct {
uint32_t dword_0;
uint32_t dword_1;
uint32_t dword_2;
uint32_t dword_3;
uint32_t dword_4;
uint32_t dword_5;
};
};
static_assert_size(xe_gpu_texture_fetch_t, sizeof(uint32_t) * 6);
// XE_GPU_REG_SHADER_CONSTANT_FETCH_*
union alignas(uint32_t) xe_gpu_fetch_group_t {
xe_gpu_texture_fetch_t texture_fetch;
struct {
xe_gpu_vertex_fetch_t vertex_fetch_0;
xe_gpu_vertex_fetch_t vertex_fetch_1;
xe_gpu_vertex_fetch_t vertex_fetch_2;
};
struct {
uint32_t dword_0;
uint32_t dword_1;
@ -1162,6 +1156,12 @@ union alignas(uint32_t) xe_gpu_fetch_group_t {
uint32_t dword_4;
uint32_t dword_5;
};
xe_gpu_texture_fetch_t texture_fetch;
struct {
xe_gpu_vertex_fetch_t vertex_fetch_0;
xe_gpu_vertex_fetch_t vertex_fetch_1;
xe_gpu_vertex_fetch_t vertex_fetch_2;
};
struct {
uint32_t type_0 : 2;
uint32_t data_0_a : 30;
@ -1291,6 +1291,12 @@ static_assert_size(xe_gpu_fetch_group_t, sizeof(uint32_t) * 6);
// 8in16, 16_16_16_16, uint, RGBA - from 16_16_16_16 uint vfetch
// (16_16_16_16 is the largest color format without special values)
union alignas(uint32_t) xe_gpu_memexport_stream_t {
struct {
uint32_t dword_0;
uint32_t dword_1;
uint32_t dword_2;
uint32_t dword_3;
};
struct {
uint32_t base_address : 30; // +0 dword_0 physical address >> 2
uint32_t const_0x1 : 2; // +30
@ -1308,12 +1314,6 @@ union alignas(uint32_t) xe_gpu_memexport_stream_t {
uint32_t index_count : 23; // +0 dword_3
uint32_t const_0x96 : 9; // +23
};
struct {
uint32_t dword_0;
uint32_t dword_1;
uint32_t dword_2;
uint32_t dword_3;
};
};
static_assert_size(xe_gpu_memexport_stream_t, sizeof(uint32_t) * 4);

View File

@ -558,11 +558,11 @@ struct xex2_header {
struct xex2_page_descriptor {
union {
xe::be<uint32_t> value; // 0x0
struct {
xex2_section_type info : 4;
uint32_t page_count : 28;
};
xe::be<uint32_t> value; // 0x0
};
char data_digest[0x14]; // 0x4
};

View File

@ -36,13 +36,13 @@ class UserProfile {
INVALID = 0xFF,
};
union Key {
uint32_t value;
struct {
uint32_t id : 14;
uint32_t unk : 2;
uint32_t size : 12;
uint32_t type : 4;
};
uint32_t value;
};
uint32_t setting_id;
Type type;

View File

@ -32,7 +32,7 @@ void XNotifyListener::Initialize(uint64_t mask, uint32_t max_version) {
}
void XNotifyListener::EnqueueNotification(XNotificationID id, uint32_t data) {
auto key = XNotificationKey{id};
auto key = XNotificationKey(id);
// Ignore if the notification doesn't match our mask.
if ((mask_ & uint64_t(1ULL << key.mask_index)) == 0) {
return;

View File

@ -13,6 +13,7 @@
#include <memory>
#include <unordered_map>
#include "xenia/base/assert.h"
#include "xenia/base/mutex.h"
#include "xenia/base/threading.h"
#include "xenia/kernel/xobject.h"
@ -22,21 +23,21 @@ namespace xe {
namespace kernel {
union XNotificationKey {
XNotificationID id;
struct {
uint32_t local_id : 16;
uint32_t version : 9;
uint32_t mask_index : 6;
uint32_t : 1;
};
XNotificationID id;
static constexpr XNotificationID get_id(uint8_t mask_index,
uint16_t local_id) {
XNotificationKey key = {};
key.mask_index = mask_index;
key.local_id = local_id;
return key.id;
constexpr XNotificationKey(
XNotificationID notification_id = XNotificationID(0))
: id(notification_id) {
static_assert_size(*this, sizeof(id));
}
constexpr operator XNotificationID() { return id; }
};
class XNotifyListener : public XObject {

View File

@ -80,6 +80,7 @@ struct HeapAllocationInfo {
// Describes a single page in the page table.
union PageEntry {
uint64_t qword;
struct {
// Base address of the allocated region in 4k pages.
uint32_t base_address : 20;
@ -95,7 +96,6 @@ union PageEntry {
uint32_t state : 2;
uint32_t reserved : 14;
};
uint64_t qword;
};
// Heap abstraction for page-based allocation.

View File

@ -47,6 +47,7 @@ struct StfsVolumeDescriptor {
uint8_t descriptor_length;
uint8_t version;
union {
uint8_t as_byte;
struct {
uint8_t read_only_format : 1; // if set, only uses a single backing-block
// per hash table (no resiliency),
@ -57,7 +58,6 @@ struct StfsVolumeDescriptor {
uint8_t directory_overallocated : 1;
uint8_t directory_index_bounds_valid : 1;
} bits;
uint8_t as_byte;
} flags;
uint16_t file_table_block_count;
uint8_t file_table_block_number_raw[3];
@ -195,12 +195,12 @@ struct SvodDeviceDescriptor {
uint8_t worker_thread_priority;
uint8_t first_fragment_hash_entry[0x14];
union {
uint8_t as_byte;
struct {
uint8_t must_be_zero_for_future_usage : 6;
uint8_t enhanced_gdf_layout : 1;
uint8_t zero_for_downlevel_clients : 1;
} bits;
uint8_t as_byte;
} features;
uint8_t num_data_blocks_raw[3];
uint8_t start_data_block_raw[3];
@ -295,8 +295,8 @@ struct XContentMetadata {
char16_t chars[64];
} title_name_raw;
union {
XContentAttributes bits;
uint8_t as_byte;
XContentAttributes bits;
} flags;
be<uint32_t> thumbnail_size;
be<uint32_t> title_thumbnail_size;