[GPU] Set VGT_DRAW_INITIATOR and use major mode from it
This commit is contained in:
parent
8204fa163a
commit
90b772a330
|
@ -1153,44 +1153,51 @@ bool CommandProcessor::ExecutePacketType3_DRAW_INDX(RingBuffer* reader,
|
||||||
// ID = dword0 & 0x3F;
|
// ID = dword0 & 0x3F;
|
||||||
// use = dword0 & 0x40;
|
// use = dword0 & 0x40;
|
||||||
uint32_t dword0 = reader->ReadAndSwap<uint32_t>(); // viz query info
|
uint32_t dword0 = reader->ReadAndSwap<uint32_t>(); // viz query info
|
||||||
uint32_t dword1 = reader->ReadAndSwap<uint32_t>();
|
reg::VGT_DRAW_INITIATOR vgt_draw_initiator;
|
||||||
uint32_t index_count = dword1 >> 16;
|
vgt_draw_initiator.value = reader->ReadAndSwap<uint32_t>();
|
||||||
auto prim_type = static_cast<PrimitiveType>(dword1 & 0x3F);
|
WriteRegister(XE_GPU_REG_VGT_DRAW_INITIATOR, vgt_draw_initiator.value);
|
||||||
|
|
||||||
bool is_indexed = false;
|
bool is_indexed = false;
|
||||||
IndexBufferInfo index_buffer_info;
|
IndexBufferInfo index_buffer_info;
|
||||||
uint32_t src_sel = (dword1 >> 6) & 0x3;
|
switch (vgt_draw_initiator.source_select) {
|
||||||
if (src_sel == 0x0) {
|
case xenos::SourceSelect::kDMA: {
|
||||||
// DI_SRC_SEL_DMA
|
|
||||||
// Indexed draw.
|
// Indexed draw.
|
||||||
is_indexed = true;
|
is_indexed = true;
|
||||||
index_buffer_info.guest_base = reader->ReadAndSwap<uint32_t>();
|
index_buffer_info.guest_base = reader->ReadAndSwap<uint32_t>();
|
||||||
uint32_t index_size = reader->ReadAndSwap<uint32_t>();
|
uint32_t index_size = reader->ReadAndSwap<uint32_t>();
|
||||||
index_buffer_info.endianness = static_cast<Endian>(index_size >> 30);
|
index_buffer_info.endianness = static_cast<Endian>(index_size >> 30);
|
||||||
index_size &= 0x00FFFFFF;
|
index_size &= 0x00FFFFFF;
|
||||||
bool index_32bit = (dword1 >> 11) & 0x1;
|
index_buffer_info.format = vgt_draw_initiator.index_size;
|
||||||
index_buffer_info.format =
|
index_size *=
|
||||||
index_32bit ? IndexFormat::kInt32 : IndexFormat::kInt16;
|
(vgt_draw_initiator.index_size == IndexFormat::kInt32) ? 4 : 2;
|
||||||
index_size *= index_32bit ? 4 : 2;
|
|
||||||
index_buffer_info.length = index_size;
|
index_buffer_info.length = index_size;
|
||||||
index_buffer_info.count = index_count;
|
index_buffer_info.count = vgt_draw_initiator.num_indices;
|
||||||
} else if (src_sel == 0x1) {
|
} break;
|
||||||
// DI_SRC_SEL_IMMEDIATE
|
case xenos::SourceSelect::kImmediate: {
|
||||||
|
// TODO(Triang3l): VGT_IMMED_DATA.
|
||||||
assert_always();
|
assert_always();
|
||||||
} else if (src_sel == 0x2) {
|
} break;
|
||||||
// DI_SRC_SEL_AUTO_INDEX
|
case xenos::SourceSelect::kAutoIndex: {
|
||||||
// Auto draw.
|
// Auto draw.
|
||||||
index_buffer_info.guest_base = 0;
|
index_buffer_info.guest_base = 0;
|
||||||
index_buffer_info.length = 0;
|
index_buffer_info.length = 0;
|
||||||
} else {
|
} break;
|
||||||
|
default: {
|
||||||
// Invalid source select.
|
// Invalid source select.
|
||||||
assert_always();
|
assert_always();
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = IssueDraw(prim_type, index_count,
|
bool success =
|
||||||
is_indexed ? &index_buffer_info : nullptr);
|
IssueDraw(vgt_draw_initiator.prim_type, vgt_draw_initiator.num_indices,
|
||||||
|
is_indexed ? &index_buffer_info : nullptr,
|
||||||
|
xenos::IsMajorModeExplicit(vgt_draw_initiator.major_mode,
|
||||||
|
vgt_draw_initiator.prim_type));
|
||||||
if (!success) {
|
if (!success) {
|
||||||
XELOGE("PM4_DRAW_INDX(%d, %d, %d): Failed in backend", index_count,
|
XELOGE("PM4_DRAW_INDX(%d, %d, %d): Failed in backend",
|
||||||
prim_type, src_sel);
|
vgt_draw_initiator.num_indices,
|
||||||
|
uint32_t(vgt_draw_initiator.prim_type),
|
||||||
|
uint32_t(vgt_draw_initiator.source_select));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1200,21 +1207,27 @@ bool CommandProcessor::ExecutePacketType3_DRAW_INDX_2(RingBuffer* reader,
|
||||||
uint32_t packet,
|
uint32_t packet,
|
||||||
uint32_t count) {
|
uint32_t count) {
|
||||||
// draw using supplied indices in packet
|
// draw using supplied indices in packet
|
||||||
uint32_t dword0 = reader->ReadAndSwap<uint32_t>();
|
reg::VGT_DRAW_INITIATOR vgt_draw_initiator;
|
||||||
uint32_t index_count = dword0 >> 16;
|
vgt_draw_initiator.value = reader->ReadAndSwap<uint32_t>();
|
||||||
auto prim_type = static_cast<PrimitiveType>(dword0 & 0x3F);
|
WriteRegister(XE_GPU_REG_VGT_DRAW_INITIATOR, vgt_draw_initiator.value);
|
||||||
uint32_t src_sel = (dword0 >> 6) & 0x3;
|
assert_true(vgt_draw_initiator.source_select ==
|
||||||
assert_true(src_sel == 0x2); // 'SrcSel=AutoIndex'
|
xenos::SourceSelect::kAutoIndex);
|
||||||
// Index buffer unused as automatic.
|
// Index buffer unused as automatic.
|
||||||
// bool index_32bit = (dword0 >> 11) & 0x1;
|
// uint32_t indices_size =
|
||||||
// uint32_t indices_size = index_count * (index_32bit ? 4 : 2);
|
// vgt_draw_initiator.num_indices *
|
||||||
|
// (vgt_draw_initiator.index_size == IndexFormat::kInt32 ? 4 : 2);
|
||||||
// uint32_t index_ptr = reader->ptr();
|
// uint32_t index_ptr = reader->ptr();
|
||||||
|
// TODO(Triang3l): VGT_IMMED_DATA.
|
||||||
reader->AdvanceRead((count - 1) * sizeof(uint32_t));
|
reader->AdvanceRead((count - 1) * sizeof(uint32_t));
|
||||||
|
|
||||||
bool success = IssueDraw(prim_type, index_count, nullptr);
|
bool success = IssueDraw(
|
||||||
|
vgt_draw_initiator.prim_type, vgt_draw_initiator.num_indices, nullptr,
|
||||||
|
xenos::IsMajorModeExplicit(vgt_draw_initiator.major_mode,
|
||||||
|
vgt_draw_initiator.prim_type));
|
||||||
if (!success) {
|
if (!success) {
|
||||||
XELOGE("PM4_DRAW_INDX_IMM(%d, %d): Failed in backend", index_count,
|
XELOGE("PM4_DRAW_INDX_IMM(%d, %d): Failed in backend",
|
||||||
prim_type);
|
vgt_draw_initiator.num_indices,
|
||||||
|
uint32_t(vgt_draw_initiator.prim_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -239,7 +239,8 @@ class CommandProcessor {
|
||||||
uint32_t dword_count) = 0;
|
uint32_t dword_count) = 0;
|
||||||
|
|
||||||
virtual bool IssueDraw(PrimitiveType prim_type, uint32_t index_count,
|
virtual bool IssueDraw(PrimitiveType prim_type, uint32_t index_count,
|
||||||
IndexBufferInfo* index_buffer_info) = 0;
|
IndexBufferInfo* index_buffer_info,
|
||||||
|
bool major_mode_explicit) = 0;
|
||||||
virtual bool IssueCopy() = 0;
|
virtual bool IssueCopy() = 0;
|
||||||
|
|
||||||
virtual void InitializeTrace() = 0;
|
virtual void InitializeTrace() = 0;
|
||||||
|
|
|
@ -1245,7 +1245,8 @@ Shader* D3D12CommandProcessor::LoadShader(ShaderType shader_type,
|
||||||
|
|
||||||
bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||||
uint32_t index_count,
|
uint32_t index_count,
|
||||||
IndexBufferInfo* index_buffer_info) {
|
IndexBufferInfo* index_buffer_info,
|
||||||
|
bool major_mode_explicit) {
|
||||||
auto device = GetD3D12Context()->GetD3D12Provider()->GetDevice();
|
auto device = GetD3D12Context()->GetD3D12Provider()->GetDevice();
|
||||||
auto& regs = *register_file_;
|
auto& regs = *register_file_;
|
||||||
|
|
||||||
|
@ -1272,8 +1273,7 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||||
|
|
||||||
// Check if using tessellation to get the correct primitive type.
|
// Check if using tessellation to get the correct primitive type.
|
||||||
bool tessellated;
|
bool tessellated;
|
||||||
if (uint32_t(primitive_type) >=
|
if (major_mode_explicit) {
|
||||||
uint32_t(PrimitiveType::kExplicitMajorModeForceStart)) {
|
|
||||||
tessellated = regs.Get<reg::VGT_OUTPUT_PATH_CNTL>().path_select ==
|
tessellated = regs.Get<reg::VGT_OUTPUT_PATH_CNTL>().path_select ==
|
||||||
xenos::VGTOutputPath::kTessellationEnable;
|
xenos::VGTOutputPath::kTessellationEnable;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -171,7 +171,8 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||||
uint32_t dword_count) override;
|
uint32_t dword_count) override;
|
||||||
|
|
||||||
bool IssueDraw(PrimitiveType primitive_type, uint32_t index_count,
|
bool IssueDraw(PrimitiveType primitive_type, uint32_t index_count,
|
||||||
IndexBufferInfo* index_buffer_info) override;
|
IndexBufferInfo* index_buffer_info,
|
||||||
|
bool major_mode_explicit) override;
|
||||||
bool IssueCopy() override;
|
bool IssueCopy() override;
|
||||||
|
|
||||||
void InitializeTrace() override;
|
void InitializeTrace() override;
|
||||||
|
|
|
@ -44,7 +44,8 @@ Shader* NullCommandProcessor::LoadShader(ShaderType shader_type,
|
||||||
|
|
||||||
bool NullCommandProcessor::IssueDraw(PrimitiveType prim_type,
|
bool NullCommandProcessor::IssueDraw(PrimitiveType prim_type,
|
||||||
uint32_t index_count,
|
uint32_t index_count,
|
||||||
IndexBufferInfo* index_buffer_info) {
|
IndexBufferInfo* index_buffer_info,
|
||||||
|
bool major_mode_explicit) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,8 @@ class NullCommandProcessor : public CommandProcessor {
|
||||||
uint32_t dword_count) override;
|
uint32_t dword_count) override;
|
||||||
|
|
||||||
bool IssueDraw(PrimitiveType prim_type, uint32_t index_count,
|
bool IssueDraw(PrimitiveType prim_type, uint32_t index_count,
|
||||||
IndexBufferInfo* index_buffer_info) override;
|
IndexBufferInfo* index_buffer_info,
|
||||||
|
bool major_mode_explicit) override;
|
||||||
bool IssueCopy() override;
|
bool IssueCopy() override;
|
||||||
|
|
||||||
void InitializeTrace() override;
|
void InitializeTrace() override;
|
||||||
|
|
|
@ -131,7 +131,10 @@ XE_GPU_REGISTER(0x2182, kDword, SQ_INTERPOLATOR_CNTL)
|
||||||
XE_GPU_REGISTER(0x2183, kDword, SQ_WRAPPING_0)
|
XE_GPU_REGISTER(0x2183, kDword, SQ_WRAPPING_0)
|
||||||
XE_GPU_REGISTER(0x2184, kDword, SQ_WRAPPING_1)
|
XE_GPU_REGISTER(0x2184, kDword, SQ_WRAPPING_1)
|
||||||
|
|
||||||
|
// These three registers are set by the command processor.
|
||||||
XE_GPU_REGISTER(0x21F9, kDword, VGT_EVENT_INITIATOR)
|
XE_GPU_REGISTER(0x21F9, kDword, VGT_EVENT_INITIATOR)
|
||||||
|
XE_GPU_REGISTER(0x21FC, kDword, VGT_DRAW_INITIATOR)
|
||||||
|
XE_GPU_REGISTER(0x21FD, kDword, VGT_IMMED_DATA)
|
||||||
|
|
||||||
XE_GPU_REGISTER(0x2200, kDword, RB_DEPTHCONTROL)
|
XE_GPU_REGISTER(0x2200, kDword, RB_DEPTHCONTROL)
|
||||||
XE_GPU_REGISTER(0x2201, kDword, RB_BLENDCONTROL0)
|
XE_GPU_REGISTER(0x2201, kDword, RB_BLENDCONTROL0)
|
||||||
|
|
|
@ -145,6 +145,22 @@ union SQ_CONTEXT_MISC {
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
union VGT_DRAW_INITIATOR {
|
||||||
|
// Different than on A2xx and R6xx/R7xx.
|
||||||
|
struct {
|
||||||
|
PrimitiveType prim_type : 6; // +0
|
||||||
|
xenos::SourceSelect source_select : 2; // +6
|
||||||
|
xenos::MajorMode major_mode : 2; // +8
|
||||||
|
uint32_t : 1; // +10
|
||||||
|
IndexFormat index_size : 1; // +11
|
||||||
|
uint32_t not_eop : 1; // +12
|
||||||
|
uint32_t : 3; // +13
|
||||||
|
uint32_t num_indices : 16; // +16
|
||||||
|
};
|
||||||
|
uint32_t value;
|
||||||
|
static constexpr Register register_index = XE_GPU_REG_VGT_DRAW_INITIATOR;
|
||||||
|
};
|
||||||
|
|
||||||
union VGT_OUTPUT_PATH_CNTL {
|
union VGT_OUTPUT_PATH_CNTL {
|
||||||
struct {
|
struct {
|
||||||
xenos::VGTOutputPath path_select : 2; // +0
|
xenos::VGTOutputPath path_select : 2; // +0
|
||||||
|
|
|
@ -40,7 +40,8 @@ Shader* VulkanCommandProcessor::LoadShader(ShaderType shader_type,
|
||||||
|
|
||||||
bool VulkanCommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
bool VulkanCommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||||
uint32_t index_count,
|
uint32_t index_count,
|
||||||
IndexBufferInfo* index_buffer_info) {
|
IndexBufferInfo* index_buffer_info,
|
||||||
|
bool major_mode_explicit) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||||
uint32_t dword_count) override;
|
uint32_t dword_count) override;
|
||||||
|
|
||||||
bool IssueDraw(PrimitiveType primitive_type, uint32_t index_count,
|
bool IssueDraw(PrimitiveType primitive_type, uint32_t index_count,
|
||||||
IndexBufferInfo* index_buffer_info) override;
|
IndexBufferInfo* index_buffer_info,
|
||||||
|
bool major_mode_explicit) override;
|
||||||
bool IssueCopy() override;
|
bool IssueCopy() override;
|
||||||
|
|
||||||
void InitializeTrace() override;
|
void InitializeTrace() override;
|
||||||
|
|
|
@ -598,7 +598,8 @@ Shader* VulkanCommandProcessor::LoadShader(ShaderType shader_type,
|
||||||
|
|
||||||
bool VulkanCommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
bool VulkanCommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||||
uint32_t index_count,
|
uint32_t index_count,
|
||||||
IndexBufferInfo* index_buffer_info) {
|
IndexBufferInfo* index_buffer_info,
|
||||||
|
bool major_mode_explicit) {
|
||||||
auto& regs = *register_file_;
|
auto& regs = *register_file_;
|
||||||
|
|
||||||
#if FINE_GRAINED_DRAW_SCOPES
|
#if FINE_GRAINED_DRAW_SCOPES
|
||||||
|
|
|
@ -81,7 +81,8 @@ class VulkanCommandProcessor : public CommandProcessor {
|
||||||
uint32_t dword_count) override;
|
uint32_t dword_count) override;
|
||||||
|
|
||||||
bool IssueDraw(PrimitiveType primitive_type, uint32_t index_count,
|
bool IssueDraw(PrimitiveType primitive_type, uint32_t index_count,
|
||||||
IndexBufferInfo* index_buffer_info) override;
|
IndexBufferInfo* index_buffer_info,
|
||||||
|
bool major_mode_explicit) override;
|
||||||
bool PopulateConstants(VkCommandBuffer command_buffer,
|
bool PopulateConstants(VkCommandBuffer command_buffer,
|
||||||
VulkanShader* vertex_shader,
|
VulkanShader* vertex_shader,
|
||||||
VulkanShader* pixel_shader);
|
VulkanShader* pixel_shader);
|
||||||
|
|
|
@ -37,12 +37,11 @@ enum class PrimitiveType : uint32_t {
|
||||||
kQuadStrip = 0x0E,
|
kQuadStrip = 0x0E,
|
||||||
kPolygon = 0x0F,
|
kPolygon = 0x0F,
|
||||||
|
|
||||||
// Starting with this primitive mode, registers like VGT_OUTPUT_PATH_CNTL have
|
// Starting with this primitive type, explicit major mode is assumed (in the
|
||||||
// effect (deduced from R6xx/R7xx registers, and Halo 3 also doesn't reset
|
// R6xx/R7xx registers, k2DCopyRectListV0 is 22, and implicit major mode is
|
||||||
// VGT_OUTPUT_PATH_CNTL after the first draw with tessellation).
|
// only used for primitive types 0 through 21) - and tessellation patches use
|
||||||
// TODO(Triang3l): Find out if VGT_DRAW_INITIATOR (0x21FC on Adreno 2xx, but
|
// the range that starts from k2DCopyRectListV0.
|
||||||
// not seen being used in games) specifies the major mode (or if it's set
|
// TODO(Triang3l): Verify if this is also true for the Xenos.
|
||||||
// somewhere else).
|
|
||||||
kExplicitMajorModeForceStart = 0x10,
|
kExplicitMajorModeForceStart = 0x10,
|
||||||
|
|
||||||
k2DCopyRectListV0 = 0x10,
|
k2DCopyRectListV0 = 0x10,
|
||||||
|
@ -460,6 +459,25 @@ typedef enum {
|
||||||
XE_GPU_INVALIDATE_MASK_ALL = 0x7FFF,
|
XE_GPU_INVALIDATE_MASK_ALL = 0x7FFF,
|
||||||
} XE_GPU_INVALIDATE_MASK;
|
} XE_GPU_INVALIDATE_MASK;
|
||||||
|
|
||||||
|
// VGT_DRAW_INITIATOR::DI_SRC_SEL_*
|
||||||
|
enum class SourceSelect : uint32_t {
|
||||||
|
kDMA,
|
||||||
|
kImmediate,
|
||||||
|
kAutoIndex,
|
||||||
|
};
|
||||||
|
|
||||||
|
// VGT_DRAW_INITIATOR::DI_MAJOR_MODE_*
|
||||||
|
enum class MajorMode : uint32_t {
|
||||||
|
kImplicit,
|
||||||
|
kExplicit,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool IsMajorModeExplicit(MajorMode major_mode,
|
||||||
|
PrimitiveType primitive_type) {
|
||||||
|
return major_mode != MajorMode::kImplicit ||
|
||||||
|
primitive_type >= PrimitiveType::kExplicitMajorModeForceStart;
|
||||||
|
}
|
||||||
|
|
||||||
// instr_arbitrary_filter_t
|
// instr_arbitrary_filter_t
|
||||||
enum class ArbitraryFilter : uint32_t {
|
enum class ArbitraryFilter : uint32_t {
|
||||||
k2x4Sym = 0,
|
k2x4Sym = 0,
|
||||||
|
|
Loading…
Reference in New Issue