[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) #pragma pack(push, 1)
union InstrKey { union InstrKey {
uint32_t value;
struct { struct {
uint32_t opcode : 8; uint32_t opcode : 8;
uint32_t dest : 5; uint32_t dest : 5;
@ -54,11 +55,10 @@ union InstrKey {
uint32_t src3 : 5; uint32_t src3 : 5;
uint32_t reserved : 4; uint32_t reserved : 4;
}; };
uint32_t value;
operator uint32_t() const { return 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(uint32_t v) : value(v) {}
InstrKey(const Instr* i) : value(0) { InstrKey(const Instr* i) : value(0) {
opcode = i->opcode->num; opcode = i->opcode->num;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -985,6 +985,10 @@ enum class FetchConstantType : uint32_t {
// XE_GPU_REG_SHADER_CONSTANT_FETCH_* // XE_GPU_REG_SHADER_CONSTANT_FETCH_*
union alignas(uint32_t) xe_gpu_vertex_fetch_t { union alignas(uint32_t) xe_gpu_vertex_fetch_t {
struct {
uint32_t dword_0;
uint32_t dword_1;
};
struct { struct {
FetchConstantType type : 2; // +0 FetchConstantType type : 2; // +0
uint32_t address : 30; // +2 address in dwords 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 size : 24; // +2 size in words
uint32_t unk1 : 6; // +26 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); 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_* // XE_GPU_REG_SHADER_CONSTANT_FETCH_*
union alignas(uint32_t) xe_gpu_texture_fetch_t { 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 { struct {
FetchConstantType type : 2; // +0 dword_0 FetchConstantType type : 2; // +0 dword_0
// Likely before the swizzle, seems logical from R5xx (SIGNED_COMP0/1/2/3 // 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 packed_mips : 1; // +11
uint32_t mip_address : 20; // +12 mip address >> 12 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); static_assert_size(xe_gpu_texture_fetch_t, sizeof(uint32_t) * 6);
// XE_GPU_REG_SHADER_CONSTANT_FETCH_* // XE_GPU_REG_SHADER_CONSTANT_FETCH_*
union alignas(uint32_t) xe_gpu_fetch_group_t { 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 { struct {
uint32_t dword_0; uint32_t dword_0;
uint32_t dword_1; uint32_t dword_1;
@ -1162,6 +1156,12 @@ union alignas(uint32_t) xe_gpu_fetch_group_t {
uint32_t dword_4; uint32_t dword_4;
uint32_t dword_5; 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 { struct {
uint32_t type_0 : 2; uint32_t type_0 : 2;
uint32_t data_0_a : 30; 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 // 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) // (16_16_16_16 is the largest color format without special values)
union alignas(uint32_t) xe_gpu_memexport_stream_t { 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 { struct {
uint32_t base_address : 30; // +0 dword_0 physical address >> 2 uint32_t base_address : 30; // +0 dword_0 physical address >> 2
uint32_t const_0x1 : 2; // +30 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 index_count : 23; // +0 dword_3
uint32_t const_0x96 : 9; // +23 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); 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 { struct xex2_page_descriptor {
union { union {
xe::be<uint32_t> value; // 0x0
struct { struct {
xex2_section_type info : 4; xex2_section_type info : 4;
uint32_t page_count : 28; uint32_t page_count : 28;
}; };
xe::be<uint32_t> value; // 0x0
}; };
char data_digest[0x14]; // 0x4 char data_digest[0x14]; // 0x4
}; };

View File

@ -36,13 +36,13 @@ class UserProfile {
INVALID = 0xFF, INVALID = 0xFF,
}; };
union Key { union Key {
uint32_t value;
struct { struct {
uint32_t id : 14; uint32_t id : 14;
uint32_t unk : 2; uint32_t unk : 2;
uint32_t size : 12; uint32_t size : 12;
uint32_t type : 4; uint32_t type : 4;
}; };
uint32_t value;
}; };
uint32_t setting_id; uint32_t setting_id;
Type type; 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) { 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. // Ignore if the notification doesn't match our mask.
if ((mask_ & uint64_t(1ULL << key.mask_index)) == 0) { if ((mask_ & uint64_t(1ULL << key.mask_index)) == 0) {
return; return;

View File

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

View File

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

View File

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