maxwell3d: Implement Conditional Rendering
Conditional Rendering takes care of conditionaly clearing or drawing depending on a set of queries. This PR implements the query checks to stablish if things can be rendered or not.
This commit is contained in:
parent
223a535f3f
commit
e42bcf2314
|
@ -249,6 +249,10 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
|
||||||
ProcessQueryGet();
|
ProcessQueryGet();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MAXWELL3D_REG_INDEX(condition.mode): {
|
||||||
|
ProcessQueryCondition();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MAXWELL3D_REG_INDEX(sync_info): {
|
case MAXWELL3D_REG_INDEX(sync_info): {
|
||||||
ProcessSyncPoint();
|
ProcessSyncPoint();
|
||||||
break;
|
break;
|
||||||
|
@ -302,6 +306,7 @@ void Maxwell3D::ProcessQueryGet() {
|
||||||
result = regs.query.query_sequence;
|
result = regs.query.query_sequence;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
result = 1;
|
||||||
UNIMPLEMENTED_MSG("Unimplemented query select type {}",
|
UNIMPLEMENTED_MSG("Unimplemented query select type {}",
|
||||||
static_cast<u32>(regs.query.query_get.select.Value()));
|
static_cast<u32>(regs.query.query_get.select.Value()));
|
||||||
}
|
}
|
||||||
|
@ -342,6 +347,45 @@ void Maxwell3D::ProcessQueryGet() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Maxwell3D::ProcessQueryCondition() {
|
||||||
|
const GPUVAddr condition_address{regs.condition.Address()};
|
||||||
|
switch (regs.condition.mode) {
|
||||||
|
case Regs::ConditionMode::Always: {
|
||||||
|
execute_on = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Regs::ConditionMode::Never: {
|
||||||
|
execute_on = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Regs::ConditionMode::ResNonZero: {
|
||||||
|
Regs::QueryCompare cmp;
|
||||||
|
memory_manager.ReadBlockUnsafe(condition_address, &cmp, sizeof(cmp));
|
||||||
|
execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Regs::ConditionMode::Equal: {
|
||||||
|
Regs::QueryCompare cmp;
|
||||||
|
memory_manager.ReadBlockUnsafe(condition_address, &cmp, sizeof(cmp));
|
||||||
|
execute_on =
|
||||||
|
cmp.initial_sequence == cmp.current_sequence && cmp.initial_mode == cmp.current_mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Regs::ConditionMode::NotEqual: {
|
||||||
|
Regs::QueryCompare cmp;
|
||||||
|
memory_manager.ReadBlockUnsafe(condition_address, &cmp, sizeof(cmp));
|
||||||
|
execute_on =
|
||||||
|
cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
UNIMPLEMENTED_MSG("Uninplemented Condition Mode!");
|
||||||
|
execute_on = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Maxwell3D::ProcessSyncPoint() {
|
void Maxwell3D::ProcessSyncPoint() {
|
||||||
const u32 sync_point = regs.sync_info.sync_point.Value();
|
const u32 sync_point = regs.sync_info.sync_point.Value();
|
||||||
const u32 increment = regs.sync_info.increment.Value();
|
const u32 increment = regs.sync_info.increment.Value();
|
||||||
|
|
|
@ -90,6 +90,20 @@ public:
|
||||||
|
|
||||||
enum class QuerySelect : u32 {
|
enum class QuerySelect : u32 {
|
||||||
Zero = 0,
|
Zero = 0,
|
||||||
|
TimeElapsed = 2,
|
||||||
|
TransformFeedbackPrimitivesGenerated = 11,
|
||||||
|
PrimitivesGenerated = 18,
|
||||||
|
SamplesPassed = 21,
|
||||||
|
TransformFeedbackUnknown = 26,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueryCompare {
|
||||||
|
u32 initial_sequence;
|
||||||
|
u32 initial_mode;
|
||||||
|
u32 unknown1;
|
||||||
|
u32 unknown2;
|
||||||
|
u32 current_sequence;
|
||||||
|
u32 current_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class QuerySyncCondition : u32 {
|
enum class QuerySyncCondition : u32 {
|
||||||
|
@ -97,6 +111,14 @@ public:
|
||||||
GreaterThan = 1,
|
GreaterThan = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ConditionMode : u32 {
|
||||||
|
Never = 0,
|
||||||
|
Always = 1,
|
||||||
|
ResNonZero = 2,
|
||||||
|
Equal = 3,
|
||||||
|
NotEqual = 4,
|
||||||
|
};
|
||||||
|
|
||||||
enum class ShaderProgram : u32 {
|
enum class ShaderProgram : u32 {
|
||||||
VertexA = 0,
|
VertexA = 0,
|
||||||
VertexB = 1,
|
VertexB = 1,
|
||||||
|
@ -815,7 +837,18 @@ public:
|
||||||
BitField<4, 1, u32> alpha_to_one;
|
BitField<4, 1, u32> alpha_to_one;
|
||||||
} multisample_control;
|
} multisample_control;
|
||||||
|
|
||||||
INSERT_PADDING_WORDS(0x7);
|
INSERT_PADDING_WORDS(0x4);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u32 address_high;
|
||||||
|
u32 address_low;
|
||||||
|
ConditionMode mode;
|
||||||
|
|
||||||
|
GPUVAddr Address() const {
|
||||||
|
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
|
||||||
|
address_low);
|
||||||
|
}
|
||||||
|
} condition;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u32 tsc_address_high;
|
u32 tsc_address_high;
|
||||||
|
@ -1169,6 +1202,10 @@ public:
|
||||||
return macro_memory;
|
return macro_memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShouldExecute() const {
|
||||||
|
return execute_on;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitializeRegisterDefaults();
|
void InitializeRegisterDefaults();
|
||||||
|
|
||||||
|
@ -1194,6 +1231,8 @@ private:
|
||||||
|
|
||||||
Upload::State upload_state;
|
Upload::State upload_state;
|
||||||
|
|
||||||
|
bool execute_on{true};
|
||||||
|
|
||||||
/// Retrieves information about a specific TIC entry from the TIC buffer.
|
/// Retrieves information about a specific TIC entry from the TIC buffer.
|
||||||
Texture::TICEntry GetTICEntry(u32 tic_index) const;
|
Texture::TICEntry GetTICEntry(u32 tic_index) const;
|
||||||
|
|
||||||
|
@ -1219,6 +1258,9 @@ private:
|
||||||
/// Handles a write to the QUERY_GET register.
|
/// Handles a write to the QUERY_GET register.
|
||||||
void ProcessQueryGet();
|
void ProcessQueryGet();
|
||||||
|
|
||||||
|
// Handles Conditional Rendering
|
||||||
|
void ProcessQueryCondition();
|
||||||
|
|
||||||
/// Handles writes to syncing register.
|
/// Handles writes to syncing register.
|
||||||
void ProcessSyncPoint();
|
void ProcessSyncPoint();
|
||||||
|
|
||||||
|
@ -1290,6 +1332,7 @@ ASSERT_REG_POSITION(clip_distance_enabled, 0x544);
|
||||||
ASSERT_REG_POSITION(point_size, 0x546);
|
ASSERT_REG_POSITION(point_size, 0x546);
|
||||||
ASSERT_REG_POSITION(zeta_enable, 0x54E);
|
ASSERT_REG_POSITION(zeta_enable, 0x54E);
|
||||||
ASSERT_REG_POSITION(multisample_control, 0x54F);
|
ASSERT_REG_POSITION(multisample_control, 0x54F);
|
||||||
|
ASSERT_REG_POSITION(condition, 0x554);
|
||||||
ASSERT_REG_POSITION(tsc, 0x557);
|
ASSERT_REG_POSITION(tsc, 0x557);
|
||||||
ASSERT_REG_POSITION(polygon_offset_factor, 0x55b);
|
ASSERT_REG_POSITION(polygon_offset_factor, 0x55b);
|
||||||
ASSERT_REG_POSITION(tic, 0x55D);
|
ASSERT_REG_POSITION(tic, 0x55D);
|
||||||
|
|
|
@ -520,7 +520,13 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::Clear() {
|
void RasterizerOpenGL::Clear() {
|
||||||
const auto& regs = system.GPU().Maxwell3D().regs;
|
const auto& maxwell3d = system.GPU().Maxwell3D();
|
||||||
|
|
||||||
|
if (!maxwell3d.ShouldExecute()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& regs = maxwell3d.regs;
|
||||||
bool use_color{};
|
bool use_color{};
|
||||||
bool use_depth{};
|
bool use_depth{};
|
||||||
bool use_stencil{};
|
bool use_stencil{};
|
||||||
|
@ -616,6 +622,11 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
|
|
||||||
MICROPROFILE_SCOPE(OpenGL_Drawing);
|
MICROPROFILE_SCOPE(OpenGL_Drawing);
|
||||||
auto& gpu = system.GPU().Maxwell3D();
|
auto& gpu = system.GPU().Maxwell3D();
|
||||||
|
|
||||||
|
if (!gpu.ShouldExecute()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto& regs = gpu.regs;
|
const auto& regs = gpu.regs;
|
||||||
|
|
||||||
SyncColorMask();
|
SyncColorMask();
|
||||||
|
|
Loading…
Reference in New Issue