From c5695c987b75628315f2189085e10eddb3442ff4 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 27 Dec 2013 16:00:59 -0600 Subject: [PATCH 01/13] Revert "Reading shake force from calibration rather than a constant" It didn't make sense. The math was nonsensical. Calibration data was somehow applied twice. I don't even. This reverts commit 4dad640d5f58c226c0e6fd757edd13fe23099856. Fixed issue 6702. --- .../Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp | 4 ++-- Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp | 10 +++------- Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h | 1 - 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp index 7f330ecc78..5f466fd897 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp @@ -107,7 +107,6 @@ void Nunchuk::GetState(u8* const data, const bool focus) } AccelData accel; - accel_cal* calib = (accel_cal*)®.calibration[0]; // tilt EmulateTilt(&accel, m_tilt, focus); @@ -117,7 +116,7 @@ void Nunchuk::GetState(u8* const data, const bool focus) // swing EmulateSwing(&accel, m_swing); // shake - EmulateShake(&accel, calib, m_shake, m_shake_step); + EmulateShake(&accel, m_shake, m_shake_step); // buttons m_buttons->GetState(&ncdata->bt, nunchuk_button_bitmasks); } @@ -155,6 +154,7 @@ void Nunchuk::GetState(u8* const data, const bool focus) } wm_accel* dt = (wm_accel*)&ncdata->ax; + accel_cal* calib = (accel_cal*)®.calibration; dt->x = u8(trim(accel.x * (calib->one_g.x - calib->zero_g.x) + calib->zero_g.x)); dt->y = u8(trim(accel.y * (calib->one_g.y - calib->zero_g.y) + calib->zero_g.y)); dt->z = u8(trim(accel.z * (calib->one_g.z - calib->zero_g.z) + calib->zero_g.z)); diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp index 4c80b1adda..f4ddd4a1db 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp @@ -87,7 +87,6 @@ const ReportFeatures reporting_mode_features[] = }; void EmulateShake(AccelData* const accel - , accel_cal* const calib , ControllerEmu::Buttons* const buttons_group , u8* const shake_step ) { @@ -96,7 +95,7 @@ void EmulateShake(AccelData* const accel auto const shake_step_max = 15; // peak G-force - double shake_intensity; + auto const shake_intensity = 3.f; // shake is a bitfield of X,Y,Z shake button states static const unsigned int btns[] = { 0x01, 0x02, 0x04 }; @@ -107,9 +106,6 @@ void EmulateShake(AccelData* const accel { if (shake & (1 << i)) { - double zero = double((&(calib->zero_g.x))[i]); - double one = double((&(calib->one_g.x))[i]); - shake_intensity = max(zero / (one - zero), (255.f - zero) / (one - zero)); (&(accel->x))[i] = std::sin(TAU * shake_step[i] / shake_step_max) * shake_intensity; shake_step[i] = (shake_step[i] + 1) % shake_step_max; } @@ -411,7 +407,6 @@ void Wiimote::GetAccelData(u8* const data, u8* const buttons) const bool has_focus = HAS_FOCUS; const bool is_sideways = m_options->settings[1]->value != 0; const bool is_upright = m_options->settings[2]->value != 0; - accel_cal* calib = (accel_cal*)&m_eeprom[0x16]; // ----TILT---- EmulateTilt(&m_accel, m_tilt, has_focus, is_sideways, is_upright); @@ -421,10 +416,11 @@ void Wiimote::GetAccelData(u8* const data, u8* const buttons) if (has_focus) { EmulateSwing(&m_accel, m_swing, is_sideways, is_upright); - EmulateShake(&m_accel, calib, m_shake, m_shake_step); + EmulateShake(&m_accel, m_shake, m_shake_step); UDPTLayer::GetAcceleration(m_udp, &m_accel); } wm_accel* dt = (wm_accel*)data; + accel_cal* calib = (accel_cal*)&m_eeprom[0x16]; double cx,cy,cz; cx=trim(m_accel.x*(calib->one_g.x-calib->zero_g.x)+calib->zero_g.x); cy=trim(m_accel.y*(calib->one_g.y-calib->zero_g.y)+calib->zero_g.y); diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h index f2afda4aa3..45cacb390e 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h @@ -74,7 +74,6 @@ struct ExtensionReg extern const ReportFeatures reporting_mode_features[]; void EmulateShake(AccelData* const accel_data - , accel_cal* const calib , ControllerEmu::Buttons* const buttons_group , u8* const shake_step); From 620bf0b3047175186deb765f55c18ee2e6a0f6bb Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 27 Dec 2013 16:35:11 -0600 Subject: [PATCH 02/13] Eliminate some Wiimote acceleration logic redundancy. Yeah, I eliminated a total of 3 LSB of accel data in the process, but no one will notice. --- .../Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp | 6 +--- .../Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp | 29 +++++++++---------- .../Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h | 6 +++- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp index 5f466fd897..6ffb5bc3a4 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp @@ -153,11 +153,7 @@ void Nunchuk::GetState(u8* const data, const bool focus) } } - wm_accel* dt = (wm_accel*)&ncdata->ax; - accel_cal* calib = (accel_cal*)®.calibration; - dt->x = u8(trim(accel.x * (calib->one_g.x - calib->zero_g.x) + calib->zero_g.x)); - dt->y = u8(trim(accel.y * (calib->one_g.y - calib->zero_g.y) + calib->zero_g.y)); - dt->z = u8(trim(accel.z * (calib->one_g.z - calib->zero_g.z) + calib->zero_g.z)); + FillRawAccelFromGForceData(*(wm_accel*)&ncdata->ax, *(accel_cal*)®.calibration, accel); } void Nunchuk::LoadDefaults(const ControllerInterface& ciface) diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp index f4ddd4a1db..d3b55759dd 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp @@ -86,6 +86,15 @@ const ReportFeatures reporting_mode_features[] = { 0, 0, 0, 0, 23 }, }; +void FillRawAccelFromGForceData(wm_accel& raw_accel, + const accel_cal& calib, + const WiimoteEmu::AccelData& accel) +{ + raw_accel.x = (u8)trim(accel.x * (calib.one_g.x - calib.zero_g.x) + calib.zero_g.x); + raw_accel.y = (u8)trim(accel.y * (calib.one_g.y - calib.zero_g.y) + calib.zero_g.y); + raw_accel.z = (u8)trim(accel.z * (calib.one_g.z - calib.zero_g.z) + calib.zero_g.z); +} + void EmulateShake(AccelData* const accel , ControllerEmu::Buttons* const buttons_group , u8* const shake_step ) @@ -402,7 +411,7 @@ void Wiimote::GetCoreData(u8* const data) *(wm_core*)data |= m_status.buttons; } -void Wiimote::GetAccelData(u8* const data, u8* const buttons) +void Wiimote::GetAccelData(u8* const data) { const bool has_focus = HAS_FOCUS; const bool is_sideways = m_options->settings[1]->value != 0; @@ -419,20 +428,8 @@ void Wiimote::GetAccelData(u8* const data, u8* const buttons) EmulateShake(&m_accel, m_shake, m_shake_step); UDPTLayer::GetAcceleration(m_udp, &m_accel); } - wm_accel* dt = (wm_accel*)data; - accel_cal* calib = (accel_cal*)&m_eeprom[0x16]; - double cx,cy,cz; - cx=trim(m_accel.x*(calib->one_g.x-calib->zero_g.x)+calib->zero_g.x); - cy=trim(m_accel.y*(calib->one_g.y-calib->zero_g.y)+calib->zero_g.y); - cz=trim(m_accel.z*(calib->one_g.z-calib->zero_g.z)+calib->zero_g.z); - dt->x=u8(cx); - dt->y=u8(cy); - dt->z=u8(cz); - if (buttons) - { - buttons[0]|=(u8(cx*4)&3)<<5; - buttons[1]|=((u8(cy*2)&1)<<5)|((u8(cz*2)&1)<<6); - } + + FillRawAccelFromGForceData(*(wm_accel*)data, *(accel_cal*)&m_eeprom[0x16], m_accel); } #define kCutoffFreq 5.0f inline void LowPassFilter(double & var, double newval, double period) @@ -679,7 +676,7 @@ void Wiimote::Update() // acceleration if (rptf.accel) - GetAccelData(data + rptf.accel, rptf.core?(data+rptf.core):NULL); + GetAccelData(data + rptf.accel); // IR if (rptf.ir) diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h index 45cacb390e..356f7aab2d 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h @@ -73,6 +73,10 @@ struct ExtensionReg extern const ReportFeatures reporting_mode_features[]; +void FillRawAccelFromGForceData(wm_accel& raw_accel, + const accel_cal& calib, + const WiimoteEmu::AccelData& accel); + void EmulateShake(AccelData* const accel_data , ControllerEmu::Buttons* const buttons_group , u8* const shake_step); @@ -133,7 +137,7 @@ protected: void UpdateButtonsStatus(bool has_focus); void GetCoreData(u8* const data); - void GetAccelData(u8* const data, u8* const buttons); + void GetAccelData(u8* const data); void GetIRData(u8* const data, bool use_accel); void GetExtData(u8* const data); From 8230da26febcadbcbf2ad3b03e0287aa485d333a Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 27 Dec 2013 17:14:45 -0600 Subject: [PATCH 03/13] Fixed issue 6245. (ISO Path's "Remove" button not being disabled when it should be) --- Source/Core/DolphinWX/Src/ConfigMain.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index 0dfa714318..28e03ae4f6 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -1221,14 +1221,7 @@ void CConfigMain::WiiSettingsChanged(wxCommandEvent& event) // ------------------- void CConfigMain::ISOPathsSelectionChanged(wxCommandEvent& WXUNUSED (event)) { - if (!ISOPaths->GetStringSelection().empty()) - { - RemoveISOPath->Enable(true); - } - else - { - RemoveISOPath->Enable(false); - } + RemoveISOPath->Enable(ISOPaths->GetSelection() != wxNOT_FOUND); } void CConfigMain::AddRemoveISOPaths(wxCommandEvent& event) @@ -1255,6 +1248,11 @@ void CConfigMain::AddRemoveISOPaths(wxCommandEvent& event) { bRefreshList = true; ISOPaths->Delete(ISOPaths->GetSelection()); + + // This seems to not be activated on Windows when it should be. wxw bug? +#ifdef _WIN32 + ISOPathsSelectionChanged(wxCommandEvent()); +#endif } // Save changes right away From e04edd89cca5133ffb542847f2c398b3a9cc16c2 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 28 Dec 2013 00:58:08 -0600 Subject: [PATCH 04/13] Support grabbing whichever OpenGL mode we are running under from GLInterface. GLES or GL --- Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h b/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h index 8e2fa4e36b..81daedae98 100644 --- a/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h +++ b/Source/Core/DolphinWX/Src/GLInterface/InterfaceBase.h @@ -16,6 +16,7 @@ public: virtual void Swap() {} virtual void UpdateFPSDisplay(const char *Text) {} virtual void SetMode(u32 mode) { s_opengl_mode = mode; } + virtual u32 GetMode() { return s_opengl_mode; } virtual bool Create(void *&window_handle) { return true; } virtual bool MakeCurrent() { return true; } virtual bool ClearCurrent() { return true; } From d8b7f4d73f9b2b8ce4a5b74a014bf597296b2bfc Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 28 Dec 2013 01:04:52 -0600 Subject: [PATCH 05/13] [Android] Support grabbing OpenGL extensions and a function for checking for support. --- Externals/GLES3/GLES3/gl3.h | 2 +- .../VideoBackends/OGL/Src/GLFunctions.cpp | 22 +++++++++++++++++++ .../Core/VideoBackends/OGL/Src/GLFunctions.h | 4 ++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Externals/GLES3/GLES3/gl3.h b/Externals/GLES3/GLES3/gl3.h index 01cbeaacf7..afee172f9c 100644 --- a/Externals/GLES3/GLES3/gl3.h +++ b/Externals/GLES3/GLES3/gl3.h @@ -996,7 +996,7 @@ GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint draw GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint* value); GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat* value); GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); -GL_APICALL const GLubyte* GL_APIENTRY glGetStringi (GLenum name, GLuint index); +//GL_APICALL const GLubyte* GL_APIENTRY glGetStringi (GLenum name, GLuint index); GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices); GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); diff --git a/Source/Core/VideoBackends/OGL/Src/GLFunctions.cpp b/Source/Core/VideoBackends/OGL/Src/GLFunctions.cpp index c91908ea11..505326b1ea 100644 --- a/Source/Core/VideoBackends/OGL/Src/GLFunctions.cpp +++ b/Source/Core/VideoBackends/OGL/Src/GLFunctions.cpp @@ -5,7 +5,9 @@ #include "DriverDetails.h" #include "GLFunctions.h" #include "Log.h" + #include +#include #ifdef USE_GLES3 PFNGLMAPBUFFERRANGEPROC glMapBufferRange; @@ -13,6 +15,7 @@ PFNGLUNMAPBUFFERPROC glUnmapBuffer; PFNGLBINDBUFFERRANGEPROC glBindBufferRange; PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; +PFNGLGETSTRINGIPROC glGetStringi; PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; @@ -49,6 +52,8 @@ PFNGLGENQUERIESPROC glGenQueries; namespace GLFunc { void *self; + std::unordered_map _extensions; + void LoadFunction(const char *name, void **func) { #ifdef USE_GLES3 @@ -67,10 +72,27 @@ namespace GLFunc #endif } + bool SupportsExt(std::string ext) + { + return _extensions.find(ext) != _extensions.end(); + } + + void InitExtensions() + { + GLint NumExtension = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &NumExtension); + for (GLint i = 0; i < NumExtension; ++i) + _extensions[std::string((const char*)glGetStringi(GL_EXTENSIONS, i))] = true; + } + void Init() { self = dlopen(NULL, RTLD_LAZY); + LoadFunction("glGetStringi", (void**)&glGetStringi); + + InitExtensions(); + LoadFunction("glUnmapBuffer", (void**)&glUnmapBuffer); LoadFunction("glBeginQuery", (void**)&glBeginQuery); LoadFunction("glEndQuery", (void**)&glEndQuery); diff --git a/Source/Core/VideoBackends/OGL/Src/GLFunctions.h b/Source/Core/VideoBackends/OGL/Src/GLFunctions.h index cbfde1276c..7cdd5476ba 100644 --- a/Source/Core/VideoBackends/OGL/Src/GLFunctions.h +++ b/Source/Core/VideoBackends/OGL/Src/GLFunctions.h @@ -10,8 +10,10 @@ typedef GLvoid* (*PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); typedef GLvoid* (*PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); typedef void (*PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); typedef GLboolean (*PFNGLUNMAPBUFFERPROC) (GLenum target); +typedef GLubyte* (*PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); typedef void (*PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + // VAOS typedef void (*PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays); typedef void (*PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays); @@ -63,6 +65,7 @@ extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; +extern PFNGLGETSTRINGIPROC glGetStringi; extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; @@ -95,5 +98,6 @@ extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding; namespace GLFunc { void Init(); + bool SupportsExt(std::string ext); } #endif From c8cdc81ce34faf3b389df14c63d59f4a9f158ed3 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 28 Dec 2013 04:43:07 -0600 Subject: [PATCH 06/13] [ARM] Implement tw/twi --- Source/Core/Core/Src/PowerPC/JitArm32/Jit.h | 1 + .../Src/PowerPC/JitArm32/JitArm_Integer.cpp | 73 ++++++++++++++++++- .../Src/PowerPC/JitArm32/JitArm_Tables.cpp | 4 +- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h index fc1911c5bf..b245a38952 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h +++ b/Source/Core/Core/Src/PowerPC/JitArm32/Jit.h @@ -187,6 +187,7 @@ public: void mtsr(UGeckoInstruction _inst); void mfsr(UGeckoInstruction _inst); void mcrxr(UGeckoInstruction _inst); + void twx(UGeckoInstruction _inst); // LoadStore void stX(UGeckoInstruction _inst); diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp index 4d79dc037e..f39ffd01a2 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Integer.cpp @@ -90,7 +90,6 @@ void JitArm::ComputeCarry(bool Carry) BIC(tmp, tmp, mask); STR(tmp, R9, PPCSTATE_OFF(spr[SPR_XER])); gpr.Unlock(tmp); - } void JitArm::GetCarryAndClear(ARMReg reg) @@ -802,7 +801,6 @@ void JitArm::cmpli(UGeckoInstruction inst) STRB(rA, R9, PPCSTATE_OFF(cr_fast) + crf); gpr.Unlock(rA); - } void JitArm::negx(UGeckoInstruction inst) @@ -950,3 +948,74 @@ void JitArm::srawix(UGeckoInstruction inst) } } +void JitArm::twx(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITIntegerOff) + + s32 a = inst.RA; + + gpr.Flush(); + fpr.Flush(); + + ARMReg RA = gpr.GetReg(); + ARMReg RB = gpr.GetReg(); + MOV(RA, inst.TO); + + if (inst.OPCD == 3) // twi + CMP(gpr.R(a), gpr.R(inst.RB)); + else // tw + { + MOVI2R(RB, (s32)(s16)inst.SIMM_16); + CMP(gpr.R(a), RB); + } + + FixupBranch al = B_CC(CC_LT); + FixupBranch ag = B_CC(CC_GT); + FixupBranch ae = B_CC(CC_EQ); + // FIXME: will never be reached. But also no known code uses it... + FixupBranch ll = B_CC(CC_VC); + FixupBranch lg = B_CC(CC_VS); + + SetJumpTarget(al); + TST(RA, 16); + FixupBranch exit1 = B_CC(CC_NEQ); + FixupBranch take1 = B(); + SetJumpTarget(ag); + TST(RA, 8); + FixupBranch exit2 = B_CC(CC_NEQ); + FixupBranch take2 = B(); + SetJumpTarget(ae); + TST(RA, 4); + FixupBranch exit3 = B_CC(CC_NEQ); + FixupBranch take3 = B(); + SetJumpTarget(ll); + TST(RA, 2); + FixupBranch exit4 = B_CC(CC_NEQ); + FixupBranch take4 = B(); + SetJumpTarget(lg); + TST(RA, 1); + FixupBranch exit5 = B_CC(CC_NEQ); + FixupBranch take5 = B(); + + SetJumpTarget(take1); + SetJumpTarget(take2); + SetJumpTarget(take3); + SetJumpTarget(take4); + SetJumpTarget(take5); + + LDR(RA, R9, PPCSTATE_OFF(Exceptions)); + MOVI2R(RB, EXCEPTION_PROGRAM); // XXX: Can be optimized + ORR(RA, RA, RB); + STR(RA, R9, PPCSTATE_OFF(Exceptions)); + WriteExceptionExit(); + + SetJumpTarget(exit1); + SetJumpTarget(exit2); + SetJumpTarget(exit3); + SetJumpTarget(exit4); + SetJumpTarget(exit5); + WriteExit(js.compilerPC + 4, 1); + + gpr.Unlock(RA, RB); +} diff --git a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp index 20c2dffc9c..7729cf498b 100644 --- a/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/JitArm32/JitArm_Tables.cpp @@ -55,7 +55,7 @@ static GekkoOPTemplate primarytable[] = {1, &JitArm::HLEFunction}, //"HLEFunction", OPTYPE_SYSTEM, FL_ENDBLOCK}}, {2, &JitArm::Default}, //"DynaBlock", OPTYPE_SYSTEM, 0}}, - {3, &JitArm::Break}, //"twi", OPTYPE_SYSTEM, FL_ENDBLOCK}}, + {3, &JitArm::twx}, //"twi", OPTYPE_SYSTEM, FL_ENDBLOCK}}, {17, &JitArm::sc}, //"sc", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, {7, &JitArm::arith}, //"mulli", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_RC_BIT, 2}}, @@ -292,7 +292,7 @@ static GekkoOPTemplate table31[] = {595, &JitArm::mfsr}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}}, {659, &JitArm::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}}, - {4, &JitArm::Break}, //"tw", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, + {4, &JitArm::twx}, //"tw", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}}, {598, &JitArm::DoNothing}, //"sync", OPTYPE_SYSTEM, 0, 2}}, {982, &JitArm::icbi}, //"icbi", OPTYPE_SYSTEM, FL_ENDBLOCK, 3}}, From 935e1fdf9913672135d0b08f66a958c817257742 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 28 Dec 2013 04:55:39 -0600 Subject: [PATCH 07/13] [Android] Enable shader cache. --- Source/Core/VideoBackends/OGL/Src/Render.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index 4d9980fc65..21c16a77e5 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -359,11 +359,7 @@ Renderer::Renderer() g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsEarlyZ = false; -#ifdef ANDROID - g_ogl_config.bSupportsGLSLCache = false; -#else g_ogl_config.bSupportsGLSLCache = true; -#endif g_ogl_config.bSupportsGLPinnedMemory = false; g_ogl_config.bSupportsGLSync = true; g_ogl_config.bSupportsGLBaseVertex = false; From a5bfdbf6cd32a66a0b45d9af11b6037137500fd5 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 28 Dec 2013 08:00:44 -0600 Subject: [PATCH 08/13] Free performance for AMD+Linux. Instead of disabling BaseVertex due to pinned_memory. Just disable pinned_memory for the ELEMENT_ARRAY_BUFFER type which has issues with baseVertex(ELEMENT_ARRAY_BUFFER)+pinned_memory. In my two tests with this, I went from 5FPS to 11FPS in one test, and 2FPS to 6FPS in another. --- Source/Core/VideoBackends/OGL/Src/Render.cpp | 3 +-- Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index 21c16a77e5..1125441fff 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -472,8 +472,7 @@ Renderer::Renderer() g_ogl_config.bSupportsGLSLCache = TO_BOOL(GLEW_ARB_get_program_binary); g_ogl_config.bSupportsGLPinnedMemory = TO_BOOL(GLEW_AMD_pinned_memory); g_ogl_config.bSupportsGLSync = TO_BOOL(GLEW_ARB_sync); - g_ogl_config.bSupportsGLBaseVertex = TO_BOOL(GLEW_ARB_draw_elements_base_vertex) && - !DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY); + g_ogl_config.bSupportsGLBaseVertex = TO_BOOL(GLEW_ARB_draw_elements_base_vertex); g_ogl_config.bSupportCoverageMSAA = TO_BOOL(GLEW_NV_framebuffer_multisample_coverage); g_ogl_config.bSupportSampleShading = TO_BOOL(GLEW_ARB_sample_shading); g_ogl_config.bSupportOGL31 = TO_BOOL(GLEW_VERSION_3_1); diff --git a/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp b/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp index 8ec9c3c1cb..1c0c3a0da0 100644 --- a/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp +++ b/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp @@ -40,7 +40,9 @@ StreamBuffer::StreamBuffer(u32 type, size_t size, StreamType uploadType) m_uploadtype = BUFFERDATA; else if(g_ogl_config.bSupportsGLSync && g_ActiveConfig.bHackedBufferUpload && (m_uploadtype & MAP_AND_RISK)) m_uploadtype = MAP_AND_RISK; - else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && (m_uploadtype & PINNED_MEMORY)) + else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && + !(DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY) && type == GL_ELEMENT_ARRAY_BUFFER) && + (m_uploadtype & PINNED_MEMORY)) m_uploadtype = PINNED_MEMORY; else if(nvidia && (m_uploadtype & BUFFERSUBDATA)) m_uploadtype = BUFFERSUBDATA; From bbde0754207c1a5dbb39f0b4fc32cbdd66d66400 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Mon, 30 Dec 2013 20:17:56 +0100 Subject: [PATCH 09/13] Software renderer: Add a zfreeze related TODO. --- Source/Core/VideoBackends/Software/Src/Rasterizer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Core/VideoBackends/Software/Src/Rasterizer.cpp b/Source/Core/VideoBackends/Software/Src/Rasterizer.cpp index fa10ac38af..377a437c64 100644 --- a/Source/Core/VideoBackends/Software/Src/Rasterizer.cpp +++ b/Source/Core/VideoBackends/Software/Src/Rasterizer.cpp @@ -385,6 +385,10 @@ void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVer float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w }; InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31); + // TODO: The zfreeze emulation is not quite correct, yet! + // Many things might prevent us from reaching this line (culling, clipping, scissoring). + // However, the zslope is always guaranteed to be calculated unless all vertices are trivially rejected during clipping! + // We're currently sloppy at this since we abort early if any of the culling/clipping/scissoring tests fail. if (!bpmem.genMode.zfreeze || !g_SWVideoConfig.bZFreeze) InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31); From 3cfa04b5cf566e3c47b395b19ab551a2dc5c6918 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 30 Dec 2013 19:26:10 +0000 Subject: [PATCH 10/13] VertexShaderManager: Remove a hardcoded projection hack. --- Source/Core/VideoCommon/Src/VertexShaderManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp index 5ec371a0ba..ca90077bc1 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderManager.cpp @@ -411,9 +411,10 @@ void VertexShaderManager::SetConstants() g_fProjectionMatrix[12] = 0.0f; g_fProjectionMatrix[13] = 0.0f; - // donkopunchstania: GC GPU rounds differently? - // -(1 + epsilon) so objects are clipped as they are on the real HW - g_fProjectionMatrix[14] = -1.00000011921f; + // donkopunchstania suggested the GC GPU might round differently + // He had thus changed this to -(1 + epsilon) to fix clipping issues. + // I (neobrain) don't think his conjecture is true and thus reverted his change. + g_fProjectionMatrix[14] = -1.0f; g_fProjectionMatrix[15] = 0.0f; SETSTAT_FT(stats.gproj_0, g_fProjectionMatrix[0]); From 3aa0a63fe636e59a770ad7ec02a728c599545f23 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sat, 23 Nov 2013 22:06:56 +0100 Subject: [PATCH 11/13] VertexShaderGen: Remove Sonic Unleashed hack. Doesn't seem to be required anymore. Either way, even if it's still needed for anything, this is not the correct way to fix the issue. --- Source/Core/VideoCommon/Src/VertexShaderGen.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp index 78b3c57dda..f0cce5d750 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp @@ -411,13 +411,6 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ // divide out.Write("o.pos.z = o.pos.w + o.pos.z * 2.0;\n"); - // Sonic Unleashed puts its final rendering at the near or - // far plane of the viewing frustrum(actually box, they use - // orthogonal projection for that), and we end up putting it - // just beyond, and the rendering gets clipped away. (The - // primitive gets dropped) - out.Write("o.pos.z = o.pos.z * 1048575.0/1048576.0;\n"); - // the next steps of the OGL pipeline are: // (x_c,y_c,z_c,w_c) = o.pos //switch to OGL spec terminology // clipping to -w_c <= (x_c,y_c,z_c) <= w_c From de16b7207c96b1dac431ae5b4d74603b528ce0f6 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Mon, 30 Dec 2013 20:37:59 +0100 Subject: [PATCH 12/13] D3D/OGL: Add a TODO noting that we don't support GX_CULL_ALL, most notably required for accurate zfreeze emulation. --- Source/Core/VideoBackends/D3D/Src/Render.cpp | 1 + Source/Core/VideoBackends/OGL/Src/Render.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index a84010c70f..5d2df67e5f 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -1167,6 +1167,7 @@ void Renderer::SetGenerationMode() }; // rastdc.FrontCounterClockwise must be false for this to work + // TODO: GX_CULL_ALL not supported, yet! gx_state.rastdc.CullMode = d3dCullModes[bpmem.genMode.cullmode]; } diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index 1125441fff..fcbbceb63b 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -1673,6 +1673,7 @@ void Renderer::SetGenerationMode() // none, ccw, cw, ccw if (bpmem.genMode.cullmode > 0) { + // TODO: GX_CULL_ALL not supported, yet! glEnable(GL_CULL_FACE); glFrontFace(bpmem.genMode.cullmode == 2 ? GL_CCW : GL_CW); } From 6d63db96e962586b13ad343e26182f9e7be7cc2b Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 30 Dec 2013 18:26:55 -0600 Subject: [PATCH 13/13] Disable primitive restart on buggy OS X Intel HD 3000 drivers. --- Source/Core/VideoBackends/OGL/Src/Render.cpp | 18 ++++++++-- Source/Core/VideoCommon/Src/DriverDetails.cpp | 35 +++++++++++-------- Source/Core/VideoCommon/Src/DriverDetails.h | 10 +++++- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/Src/Render.cpp b/Source/Core/VideoBackends/OGL/Src/Render.cpp index fcbbceb63b..7204ab0d68 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Src/Render.cpp @@ -260,6 +260,7 @@ void InitDriverInfo() DriverDetails::Vendor vendor = DriverDetails::VENDOR_UNKNOWN; DriverDetails::Driver driver = DriverDetails::DRIVER_UNKNOWN; double version = 0.0; + u32 family = 0; // Get the vendor first if (svendor == "NVIDIA Corporation" && srenderer != "NVIDIA Tegra") @@ -321,11 +322,23 @@ void InitDriverInfo() version = 100*major + 10*minor + release; } break; + case DriverDetails::VENDOR_INTEL: // Happens in OS X + sscanf(g_ogl_config.gl_renderer, "Intel HD Graphics %d", &family); + /* + int glmajor = 0; + int glminor = 0; + int major = 0; + int minor = 0; + int release = 0; + sscanf(g_ogl_config.gl_version, "%d.%d INTEL-%d.%d.%d", &glmajor, &glminor, &major, &minor, &release); + version = 10000*major + 1000*minor + release; + */ + break; // We don't care about these default: break; } - DriverDetails::Init(vendor, driver, version); + DriverDetails::Init(vendor, driver, version, family); } // Init functions @@ -466,7 +479,8 @@ Renderer::Renderer() g_Config.backend_info.bSupportsDualSourceBlend = TO_BOOL(GLEW_ARB_blend_func_extended); g_Config.backend_info.bSupportsGLSLUBO = TO_BOOL(GLEW_ARB_uniform_buffer_object); - g_Config.backend_info.bSupportsPrimitiveRestart = TO_BOOL(GLEW_VERSION_3_1) || TO_BOOL(GLEW_NV_primitive_restart); + g_Config.backend_info.bSupportsPrimitiveRestart = !DriverDetails::HasBug(DriverDetails::BUG_PRIMITIVERESTART) && + (TO_BOOL(GLEW_VERSION_3_1) || TO_BOOL(GLEW_NV_primitive_restart)); g_Config.backend_info.bSupportsEarlyZ = TO_BOOL(GLEW_ARB_shader_image_load_store); g_ogl_config.bSupportsGLSLCache = TO_BOOL(GLEW_ARB_get_program_binary); diff --git a/Source/Core/VideoCommon/Src/DriverDetails.cpp b/Source/Core/VideoCommon/Src/DriverDetails.cpp index 64e8810d20..027908442f 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.cpp +++ b/Source/Core/VideoCommon/Src/DriverDetails.cpp @@ -14,6 +14,7 @@ namespace DriverDetails u32 m_os; // Which OS has the issue Vendor m_vendor; // Which vendor has the error Driver m_driver; // Which driver has the error + s32 m_family; // Which family of hardware has the issue Bug m_bug; // Which bug it is double m_versionstart; // When it started double m_versionend; // When it ended @@ -33,34 +34,37 @@ namespace DriverDetails Vendor m_vendor = VENDOR_UNKNOWN; Driver m_driver = DRIVER_UNKNOWN; + s32 m_family = 0.0; double m_version = 0.0; // This is a list of all known bugs for each vendor // We use this to check if the device and driver has a issue BugInfo m_known_bugs[] = { - {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, 46.0, true}, - {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, 46.0, true}, - {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENINFOLOG, -1.0, 46.0, true}, - {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_ANNIHILATEDUBOS, 41.0, 46.0, true}, - {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENSWAP, -1.0, 46.0, true}, - {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENBUFFERSTREAM, -1.0, -1.0, true}, - {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENTEXTURESIZE, -1.0, -1.0, true}, - {OS_ALL, VENDOR_ARM, DRIVER_ARM_T6XX, BUG_BROKENBUFFERSTREAM, -1.0, -1.0, true}, - {OS_ALL, VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENUBO, 900, 916, true}, - {OS_ALL, VENDOR_MESA, DRIVER_R600, BUG_BROKENUBO, 900, 913, true}, - {OS_ALL, VENDOR_MESA, DRIVER_I965, BUG_BROKENUBO, 900, 920, true}, - {OS_ALL, VENDOR_ATI, DRIVER_ATI, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true}, - {OS_LINUX, VENDOR_ATI, DRIVER_ATI, BUG_BROKENPINNEDMEMORY, -1.0, -1.0, true}, - {OS_ALL, VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true}, + {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_NODYNUBOACCESS, 14.0, 46.0, true}, + {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENCENTROID, 14.0, 46.0, true}, + {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENINFOLOG, -1.0, 46.0, true}, + {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_ANNIHILATEDUBOS, 41.0, 46.0, true}, + {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENSWAP, -1.0, 46.0, true}, + {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENBUFFERSTREAM, -1.0, -1.0, true}, + {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENTEXTURESIZE, -1.0, -1.0, true}, + {OS_ALL, VENDOR_ARM, DRIVER_ARM_T6XX, -1, BUG_BROKENBUFFERSTREAM, -1.0, -1.0, true}, + {OS_ALL, VENDOR_MESA, DRIVER_NOUVEAU, -1, BUG_BROKENUBO, 900, 916, true}, + {OS_ALL, VENDOR_MESA, DRIVER_R600, -1, BUG_BROKENUBO, 900, 913, true}, + {OS_ALL, VENDOR_MESA, DRIVER_I965, -1, BUG_BROKENUBO, 900, 920, true}, + {OS_ALL, VENDOR_ATI, DRIVER_ATI, -1, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true}, + {OS_LINUX, VENDOR_ATI, DRIVER_ATI, -1, BUG_BROKENPINNEDMEMORY, -1.0, -1.0, true}, + {OS_ALL, VENDOR_MESA, DRIVER_NOUVEAU, -1, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true}, + {OS_OSX, VENDOR_INTEL, DRIVER_INTEL, 3000, BUG_PRIMITIVERESTART, -1.0, -1.0, true}, }; std::map m_bugs; - void Init(Vendor vendor, Driver driver, const double version) + void Init(Vendor vendor, Driver driver, const double version, const s32 family) { m_vendor = vendor; m_driver = driver; m_version = version; + m_family = family; if (driver == DRIVER_UNKNOWN) switch(vendor) @@ -91,6 +95,7 @@ namespace DriverDetails ( bug.m_os & m_os ) && ( bug.m_vendor == m_vendor || bug.m_vendor == VENDOR_ALL ) && ( bug.m_driver == m_driver || bug.m_driver == DRIVER_ALL ) && + ( bug.m_family == m_family || bug.m_family == -1) && ( bug.m_versionstart <= m_version || bug.m_versionstart == -1 ) && ( bug.m_versionend > m_version || bug.m_versionend == -1 ) ) diff --git a/Source/Core/VideoCommon/Src/DriverDetails.h b/Source/Core/VideoCommon/Src/DriverDetails.h index 1b024cefca..ec2fc82a3b 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.h +++ b/Source/Core/VideoCommon/Src/DriverDetails.h @@ -141,10 +141,18 @@ namespace DriverDetails // Ended Version: -1 // If a shader includes a textureSize function call then the shader compiler will call abort() BUG_BROKENTEXTURESIZE, + // Bug: Intel HD 3000 on OS X has broken primitive restart + // Affected devices: Intel HD 3000 + // Affected OS: OS X + // Started Version: -1 + // Ended Version: -1 + // The drivers on OS X has broken primitive restart. + // Intel HD 4000 series isn't affected by the bug + BUG_PRIMITIVERESTART, }; // Initializes our internal vendor, device family, and driver version - void Init(Vendor vendor, Driver driver, const double version); + void Init(Vendor vendor, Driver driver, const double version, const s32 family); // Once Vendor and driver version is set, this will return if it has the applicable bug passed to it. bool HasBug(Bug bug);