From 0c90253a5dddc5da1ca056773eaae1a16ca53836 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 30 May 2017 13:01:51 +0300 Subject: [PATCH 1/3] Fixed potentially broken portal rendering after OpenGL context change https://forum.zdoom.org/viewtopic.php?t=56393 --- src/gl/renderer/gl_renderer.cpp | 5 +++++ src/gl/scene/gl_portal.cpp | 16 +++++++++++++++- src/gl/scene/gl_portal.h | 3 +++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 51fbd1f90..77d8d6bc3 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -50,6 +50,7 @@ #include "gl/data/gl_data.h" #include "gl/data/gl_vertexbuffer.h" #include "gl/scene/gl_drawinfo.h" +#include "gl/scene/gl_portal.h" #include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_ambientshader.h" #include "gl/shaders/gl_bloomshader.h" @@ -184,10 +185,14 @@ void FGLRenderer::Initialize(int width, int height) mShaderManager = new FShaderManager; mSamplerManager = new FSamplerManager; gl_LoadModels(); + + GLPortal::Initialize(); } FGLRenderer::~FGLRenderer() { + GLPortal::Shutdown(); + gl_FlushModels(); AActor::DeleteAllAttachedLights(); FMaterial::FlushAll(); diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index 93073d722..b5671923f 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -205,7 +205,6 @@ bool GLPortal::Start(bool usestencil, bool doquery) else if (gl_noquery) doquery = false; // If occlusion query is supported let's use it to avoid rendering portals that aren't visible - if (!QueryObject && doquery) glGenQueries(1, &QueryObject); if (QueryObject) { glBeginQuery(GL_SAMPLES_PASSED, QueryObject); @@ -1264,6 +1263,21 @@ void GLEEHorizonPortal::DrawContents() } +void GLPortal::Initialize() +{ + assert(0 == QueryObject); + glGenQueries(1, &QueryObject); +} + +void GLPortal::Shutdown() +{ + if (0 != QueryObject) + { + glDeleteQueries(1, &QueryObject); + QueryObject = 0; + } +} + const char *GLSkyPortal::GetName() { return "Sky"; } const char *GLSkyboxPortal::GetName() { return "Skybox"; } const char *GLSectorStackPortal::GetName() { return "Sectorstack"; } diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index 128db2dc8..9ef8cf5f7 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -177,6 +177,9 @@ public: static bool RenderFirstSkyPortal(int recursion); static void EndFrame(); static GLPortal * FindPortal(const void * src); + + static void Initialize(); + static void Shutdown(); }; struct GLLinePortal : public GLPortal From 62bac1d612a83e9a1823e761dfd16b5cef991e25 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 30 May 2017 18:09:51 +0300 Subject: [PATCH 2/3] Added check for nullptr to CLSS and META instructions of scripting VM https://forum.zdoom.org/viewtopic.php?t=56667 --- src/scripting/vm/vmexec.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 7e8a53a6a..d5b8ba6b1 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -37,6 +37,16 @@ #error vmexec.h must not be #included outside vmexec.cpp. Use vm.h instead. #endif +static PClass* GetClass(void* ptr) +{ + if (nullptr == ptr) + { + ThrowAbortException(X_READ_NIL, nullptr); + } + + return static_cast(ptr)->GetClass(); +} + static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) { #if COMPGOTO @@ -140,12 +150,12 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) OP(CLSS): ASSERTA(a); ASSERTA(B); - reg.a[a] = ((DObject*)reg.a[B])->GetClass(); // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer... + reg.a[a] = GetClass(reg.a[B]); NEXTOP; OP(META): ASSERTA(a); ASSERTA(B); - reg.a[a] = ((DObject*)reg.a[B])->GetClass()->Meta; // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer... + reg.a[a] = GetClass(reg.a[B])->Meta; NEXTOP; OP(LB): From b50123ec6bd08fe1ebdbd0eea7ec6c4c8a27eb22 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 30 May 2017 17:50:56 +0200 Subject: [PATCH 3/3] - avoid function call in VM code. - return after calling ThrowAbortException because this avoids storing some register variables on the stack. --- src/scripting/vm/vmexec.cpp | 2 +- src/scripting/vm/vmexec.h | 52 ++++++++++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index eb212a646..cc88a0eaa 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -101,7 +101,7 @@ void ThrowVMException(VMException *x); } #define GETADDR(a,o,x) \ - if (a == NULL) { ThrowAbortException(x, nullptr); } \ + if (a == NULL) { ThrowAbortException(x, nullptr); return 0; } \ ptr = (VM_SBYTE *)a + o #ifdef NDEBUG diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index d5b8ba6b1..ec5da180f 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -37,16 +37,6 @@ #error vmexec.h must not be #included outside vmexec.cpp. Use vm.h instead. #endif -static PClass* GetClass(void* ptr) -{ - if (nullptr == ptr) - { - ThrowAbortException(X_READ_NIL, nullptr); - } - - return static_cast(ptr)->GetClass(); -} - static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) { #if COMPGOTO @@ -149,14 +139,30 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) NEXTOP; OP(CLSS): + { ASSERTA(a); ASSERTA(B); - reg.a[a] = GetClass(reg.a[B]); + DObject *o = (DObject*)reg.a[B]; + if (o == nullptr) + { + ThrowAbortException(X_READ_NIL, nullptr); + return 0; + } + reg.a[a] = o->GetClass(); NEXTOP; + } OP(META): + { ASSERTA(a); ASSERTA(B); - reg.a[a] = GetClass(reg.a[B])->Meta; + DObject *o = (DObject*)reg.a[B]; + if (o == nullptr) + { + ThrowAbortException(X_READ_NIL, nullptr); + return 0; + } + reg.a[a] = o->GetClass()->Meta; NEXTOP; + } OP(LB): ASSERTD(a); ASSERTA(B); ASSERTKD(C); @@ -825,15 +831,18 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (cls->ConstructNative == nullptr) { ThrowAbortException(X_OTHER, "Class %s requires native construction", cls->TypeName.GetChars()); + return 0; } if (cls->bAbstract) { ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars()); + return 0; } // Creating actors here must be outright prohibited, if (cls->IsDescendantOf(NAME_Actor)) { ThrowAbortException(X_OTHER, "Cannot create actors with 'new'"); + return 0; } // [ZZ] validate readonly and between scope construction c = C; @@ -888,6 +897,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[a] >= BC) { ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", BC, reg.d[a]); + return 0; } NEXTOP; @@ -896,6 +906,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[a] >= konstd[BC]) { ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", konstd[BC], reg.d[a]); + return 0; } NEXTOP; @@ -904,6 +915,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[a] >= reg.d[B]) { ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Max.index = %u, current index = %u\n", reg.d[B], reg.d[a]); + return 0; } NEXTOP; @@ -1051,6 +1063,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = reg.d[B] / reg.d[C]; NEXTOP; @@ -1059,6 +1072,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (konstd[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = reg.d[B] / konstd[C]; NEXTOP; @@ -1067,6 +1081,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = konstd[B] / reg.d[C]; NEXTOP; @@ -1076,6 +1091,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = int((unsigned)reg.d[B] / (unsigned)reg.d[C]); NEXTOP; @@ -1084,6 +1100,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (konstd[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = int((unsigned)reg.d[B] / (unsigned)konstd[C]); NEXTOP; @@ -1092,6 +1109,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = int((unsigned)konstd[B] / (unsigned)reg.d[C]); NEXTOP; @@ -1101,6 +1119,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = reg.d[B] % reg.d[C]; NEXTOP; @@ -1109,6 +1128,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (konstd[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = reg.d[B] % konstd[C]; NEXTOP; @@ -1117,6 +1137,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = konstd[B] % reg.d[C]; NEXTOP; @@ -1126,6 +1147,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = int((unsigned)reg.d[B] % (unsigned)reg.d[C]); NEXTOP; @@ -1134,6 +1156,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (konstd[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = int((unsigned)reg.d[B] % (unsigned)konstd[C]); NEXTOP; @@ -1142,6 +1165,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.d[C] == 0) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.d[a] = int((unsigned)konstd[B] % (unsigned)reg.d[C]); NEXTOP; @@ -1298,6 +1322,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.f[C] == 0.) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.f[a] = reg.f[B] / reg.f[C]; NEXTOP; @@ -1306,6 +1331,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (konstf[C] == 0.) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.f[a] = reg.f[B] / konstf[C]; NEXTOP; @@ -1314,6 +1340,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (reg.f[C] == 0.) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.f[a] = konstf[B] / reg.f[C]; NEXTOP; @@ -1325,6 +1352,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) if (fc == 0.) { ThrowAbortException(X_DIVISION_BY_ZERO, nullptr); + return 0; } reg.f[a] = luai_nummod(fb, fc); NEXTOP;