Skip to content

Commit ef1aeac

Browse files
authored
Implement gl.ClearAttachmentFBO() in a cleaner way (#1954)
1 parent 0fbd88a commit ef1aeac

File tree

3 files changed

+187
-23
lines changed

3 files changed

+187
-23
lines changed

rts/Lua/LuaFBOs.cpp

Lines changed: 175 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "fmt/format.h"
1919

2020
#include "System/Misc/TracyDefs.h"
21+
#include "Rendering/GL/FBO.h"
22+
#include "Rendering/GlobalRendering.h"
2123

2224

2325
/******************************************************************************
@@ -28,7 +30,7 @@
2830
LuaFBOs::~LuaFBOs()
2931
{
3032
RECOIL_DETAILED_TRACY_ZONE;
31-
for (const FBO* fbo: fbos) {
33+
for (const auto* fbo: fbos) {
3234
glDeleteFramebuffersEXT(1, &fbo->id);
3335
}
3436
}
@@ -48,6 +50,9 @@ bool LuaFBOs::PushEntries(lua_State* L)
4850
REGISTER_LUA_CFUNC(ActiveFBO);
4951
REGISTER_LUA_CFUNC(RawBindFBO);
5052

53+
if (GLAD_GL_VERSION_3_0)
54+
REGISTER_LUA_CFUNC(ClearAttachmentFBO);
55+
5156
if (GLAD_GL_EXT_framebuffer_blit)
5257
REGISTER_LUA_CFUNC(BlitFBO);
5358

@@ -128,17 +133,17 @@ static GLenum ParseAttachment(const std::string& name)
128133
/******************************************************************************/
129134
/******************************************************************************/
130135

131-
const LuaFBOs::FBO* LuaFBOs::GetLuaFBO(lua_State* L, int index)
136+
const LuaFBOs::LuaFBO* LuaFBOs::GetLuaFBO(lua_State* L, int index)
132137
{
133138
RECOIL_DETAILED_TRACY_ZONE;
134-
return static_cast<FBO*>(LuaUtils::GetUserData(L, index, "FBO"));
139+
return static_cast<LuaFBO*>(LuaUtils::GetUserData(L, index, "FBO"));
135140
}
136141

137142

138143
/******************************************************************************/
139144
/******************************************************************************/
140145

141-
void LuaFBOs::FBO::Init(lua_State* L)
146+
void LuaFBOs::LuaFBO::Init(lua_State* L)
142147
{
143148
RECOIL_DETAILED_TRACY_ZONE;
144149
index = -1u;
@@ -151,7 +156,7 @@ void LuaFBOs::FBO::Init(lua_State* L)
151156
}
152157

153158

154-
void LuaFBOs::FBO::Free(lua_State* L)
159+
void LuaFBOs::LuaFBO::Free(lua_State* L)
155160
{
156161
RECOIL_DETAILED_TRACY_ZONE;
157162
if (luaRef == LUA_NOREF)
@@ -184,7 +189,7 @@ void LuaFBOs::FBO::Free(lua_State* L)
184189
int LuaFBOs::meta_gc(lua_State* L)
185190
{
186191
RECOIL_DETAILED_TRACY_ZONE;
187-
FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
192+
auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
188193
fbo->Free(L);
189194
return 0;
190195
}
@@ -193,7 +198,7 @@ int LuaFBOs::meta_gc(lua_State* L)
193198
int LuaFBOs::meta_index(lua_State* L)
194199
{
195200
RECOIL_DETAILED_TRACY_ZONE;
196-
const FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
201+
const auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
197202

198203
if (fbo->luaRef == LUA_NOREF)
199204
return 0;
@@ -209,7 +214,7 @@ int LuaFBOs::meta_index(lua_State* L)
209214
int LuaFBOs::meta_newindex(lua_State* L)
210215
{
211216
RECOIL_DETAILED_TRACY_ZONE;
212-
FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
217+
auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
213218

214219
if (fbo->luaRef == LUA_NOREF)
215220
return 0;
@@ -264,7 +269,7 @@ bool LuaFBOs::AttachObject(
264269
const char* funcName,
265270
lua_State* L,
266271
int index,
267-
FBO* fbo,
272+
LuaFBO* fbo,
268273
GLenum attachID,
269274
GLenum attachTarget,
270275
GLenum attachLevel
@@ -353,7 +358,7 @@ void LuaFBOs::AttachObjectTexTarget(const char* funcName, GLenum fboTarget, GLen
353358
bool LuaFBOs::ApplyAttachment(
354359
lua_State* L,
355360
int index,
356-
FBO* fbo,
361+
LuaFBO* fbo,
357362
const GLenum attachID
358363
) {
359364
RECOIL_DETAILED_TRACY_ZONE;
@@ -437,7 +442,7 @@ bool LuaFBOs::ApplyDrawBuffers(lua_State* L, int index)
437442
*/
438443
int LuaFBOs::CreateFBO(lua_State* L)
439444
{
440-
FBO fbo;
445+
LuaFBO fbo;
441446
fbo.Init(L);
442447

443448
const int table = 1;
@@ -468,7 +473,7 @@ int LuaFBOs::CreateFBO(lua_State* L)
468473
glBindFramebufferEXT(fbo.target, fbo.id);
469474

470475

471-
FBO* fboPtr = static_cast<FBO*>(lua_newuserdata(L, sizeof(FBO)));
476+
auto* fboPtr = static_cast<LuaFBO*>(lua_newuserdata(L, sizeof(LuaFBO)));
472477
*fboPtr = fbo;
473478

474479
luaL_getmetatable(L, "FBO");
@@ -517,7 +522,7 @@ int LuaFBOs::DeleteFBO(lua_State* L)
517522
if (lua_isnil(L, 1))
518523
return 0;
519524

520-
FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
525+
auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
521526
fbo->Free(L);
522527
return 0;
523528
}
@@ -537,7 +542,7 @@ int LuaFBOs::IsValidFBO(lua_State* L)
537542
return 1;
538543
}
539544

540-
const FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
545+
const auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
541546

542547
if ((fbo->id == 0) || (fbo->luaRef == LUA_NOREF)) {
543548
lua_pushboolean(L, false);
@@ -580,7 +585,7 @@ int LuaFBOs::ActiveFBO(lua_State* L)
580585
RECOIL_DETAILED_TRACY_ZONE;
581586
CheckDrawingEnabled(L, __func__);
582587

583-
const FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
588+
const auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
584589

585590
if (fbo->id == 0)
586591
return 0;
@@ -664,7 +669,7 @@ int LuaFBOs::RawBindFBO(lua_State* L)
664669
return 0;
665670
}
666671

667-
const FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
672+
const auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
668673

669674
if (fbo->id == 0)
670675
return 0;
@@ -731,8 +736,8 @@ int LuaFBOs::BlitFBO(lua_State* L)
731736
return 0;
732737
}
733738

734-
const FBO* fboSrc = (lua_isnil(L, 1))? nullptr: static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
735-
const FBO* fboDst = (lua_isnil(L, 6))? nullptr: static_cast<FBO*>(luaL_checkudata(L, 6, "FBO"));
739+
const auto* fboSrc = (lua_isnil(L, 1))? nullptr: static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
740+
const auto* fboDst = (lua_isnil(L, 6))? nullptr: static_cast<LuaFBO*>(luaL_checkudata(L, 6, "FBO"));
736741

737742
// if passed a non-nil arg, userdatum buffer must always be valid
738743
// otherwise the default framebuffer is substituted as its target
@@ -767,5 +772,157 @@ int LuaFBOs::BlitFBO(lua_State* L)
767772
}
768773

769774

775+
namespace Impl {
776+
template<class Type, auto glClearBufferFuncPtr>
777+
static inline void ClearBuffer(lua_State* L, int startIdx, GLenum bufferType, GLint drawBuffer) {
778+
Type values[4];
779+
values[0] = spring::SafeCast<Type>(luaL_optnumber(L, startIdx + 0, 0));
780+
values[1] = spring::SafeCast<Type>(luaL_optnumber(L, startIdx + 1, 0));
781+
values[2] = spring::SafeCast<Type>(luaL_optnumber(L, startIdx + 2, 0));
782+
values[3] = spring::SafeCast<Type>(luaL_optnumber(L, startIdx + 3, 0));
783+
(*glClearBufferFuncPtr)(bufferType, drawBuffer, values);
784+
}
785+
}
786+
787+
/*** needs `Platform.glslVersionNum >= 300`
788+
* Clears the "attachment" of the currently bound FBO type "target" with "clearValues"
789+
*
790+
* @function gl.ClearAttachmentFBO
791+
* @param target number? (Default: GL.FRAMEBUFFER)
792+
* @param attachment GL|string (e.g. `"color0"` or `GL.COLOR_ATTACHMENT0`)
793+
* @param clearValue0 number
794+
* @param clearValue1 number
795+
* @param clearValue2 number
796+
* @param clearValue3 number
797+
*/
798+
799+
int LuaFBOs::ClearAttachmentFBO(lua_State* L)
800+
{
801+
const auto ReportErrorAndReturn = [L](const char* errMsg = "", const char* func = __func__) {
802+
LOG_L(L_ERROR, "[gl.%s] Error: %s", func, errMsg);
803+
lua_pushboolean(L, false);
804+
return 1;
805+
};
806+
807+
#ifdef DEBUG
808+
glClearErrors("gl", __func__, globalRendering->glDebugErrors);
809+
#endif
810+
811+
int nextArg = 1;
812+
813+
GLenum target = luaL_optint(L, nextArg++, GL_FRAMEBUFFER);
814+
GLenum queryType = 0;
815+
switch (target)
816+
{
817+
case GL_READ_FRAMEBUFFER:
818+
queryType = GL_READ_FRAMEBUFFER_BINDING;
819+
break;
820+
case GL_DRAW_FRAMEBUFFER: [[fallthrough]];
821+
case GL_FRAMEBUFFER:
822+
queryType = GL_DRAW_FRAMEBUFFER_BINDING;
823+
break;
824+
default:
825+
return ReportErrorAndReturn(fmt::format("invalid target type({}) Only GL.READ_FRAMEBUFFER|GL.DRAW_FRAMEBUFFER|GL.FRAMEBUFFER are accepted", target).c_str());
826+
}
827+
828+
GLint fboID = 0;
829+
glGetIntegerv(queryType, &fboID);
830+
831+
if (fboID == 0)
832+
return ReportErrorAndReturn(fmt::format("no non-default fbo object is bound for target({})", target).c_str());
833+
834+
835+
GLenum bufferType = 0;
836+
GLenum attachment = 0;
837+
GLenum drawBuffer = 0;
838+
839+
if (lua_isstring(L, nextArg)) {
840+
const char* attachmentStr = luaL_checkstring(L, nextArg++);
841+
switch (hashString(attachmentStr)) {
842+
case hashString("color0"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT0; drawBuffer = 0; } break;
843+
case hashString("color1"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT1; drawBuffer = 1; } break;
844+
case hashString("color2"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT2; drawBuffer = 2; } break;
845+
case hashString("color3"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT3; drawBuffer = 3; } break;
846+
case hashString("color4"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT4; drawBuffer = 4; } break;
847+
case hashString("color5"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT5; drawBuffer = 5; } break;
848+
case hashString("color6"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT6; drawBuffer = 6; } break;
849+
case hashString("color7"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT7; drawBuffer = 7; } break;
850+
case hashString("color8"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT8; drawBuffer = 8; } break;
851+
case hashString("color9"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT9; drawBuffer = 9; } break;
852+
case hashString("color10"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT10; drawBuffer = 10; } break;
853+
case hashString("color11"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT11; drawBuffer = 11; } break;
854+
case hashString("color12"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT12; drawBuffer = 12; } break;
855+
case hashString("color13"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT13; drawBuffer = 13; } break;
856+
case hashString("color14"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT14; drawBuffer = 14; } break;
857+
case hashString("color15"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT15; drawBuffer = 15; } break;
858+
case hashString("depth"): { bufferType = GL_DEPTH; attachment = GL_DEPTH_ATTACHMENT; drawBuffer = 0; } break;
859+
case hashString("stencil"): { bufferType = GL_STENCIL; attachment = GL_STENCIL_ATTACHMENT; drawBuffer = 0; } break;
860+
default:
861+
return ReportErrorAndReturn(fmt::format("invalid attachment string ({})", attachmentStr).c_str());
862+
}
863+
}
864+
else if (lua_isnumber(L, nextArg)) {
865+
switch (attachment = luaL_checkint(L, nextArg++)) {
866+
case GL_COLOR_ATTACHMENT0: { bufferType = GL_COLOR; drawBuffer = 0; } break;
867+
case GL_COLOR_ATTACHMENT1: { bufferType = GL_COLOR; drawBuffer = 1; } break;
868+
case GL_COLOR_ATTACHMENT2: { bufferType = GL_COLOR; drawBuffer = 2; } break;
869+
case GL_COLOR_ATTACHMENT3: { bufferType = GL_COLOR; drawBuffer = 3; } break;
870+
case GL_COLOR_ATTACHMENT4: { bufferType = GL_COLOR; drawBuffer = 4; } break;
871+
case GL_COLOR_ATTACHMENT5: { bufferType = GL_COLOR; drawBuffer = 5; } break;
872+
case GL_COLOR_ATTACHMENT6: { bufferType = GL_COLOR; drawBuffer = 6; } break;
873+
case GL_COLOR_ATTACHMENT7: { bufferType = GL_COLOR; drawBuffer = 7; } break;
874+
case GL_COLOR_ATTACHMENT8: { bufferType = GL_COLOR; drawBuffer = 8; } break;
875+
case GL_COLOR_ATTACHMENT9: { bufferType = GL_COLOR; drawBuffer = 9; } break;
876+
case GL_COLOR_ATTACHMENT10: { bufferType = GL_COLOR; drawBuffer = 10; } break;
877+
case GL_COLOR_ATTACHMENT11: { bufferType = GL_COLOR; drawBuffer = 11; } break;
878+
case GL_COLOR_ATTACHMENT12: { bufferType = GL_COLOR; drawBuffer = 12; } break;
879+
case GL_COLOR_ATTACHMENT13: { bufferType = GL_COLOR; drawBuffer = 13; } break;
880+
case GL_COLOR_ATTACHMENT14: { bufferType = GL_COLOR; drawBuffer = 14; } break;
881+
case GL_COLOR_ATTACHMENT15: { bufferType = GL_COLOR; drawBuffer = 15; } break;
882+
case GL_DEPTH_ATTACHMENT: { bufferType = GL_DEPTH; drawBuffer = 0; } break;
883+
case GL_STENCIL_ATTACHMENT: { bufferType = GL_STENCIL; drawBuffer = 0; } break;
884+
default:
885+
return ReportErrorAndReturn(fmt::format("invalid attachment type ({})", attachment).c_str());
886+
}
887+
}
888+
889+
GLint attachmentType = GL_NONE;
890+
glGetFramebufferAttachmentParameteriv(target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);
891+
892+
if (attachmentType == GL_NONE || attachmentType == GL_FRAMEBUFFER_DEFAULT)
893+
return ReportErrorAndReturn(fmt::format("invalid attachment object type ({})", attachmentType).c_str());
894+
895+
GLint objectId = 0;
896+
glGetFramebufferAttachmentParameteriv(target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &objectId);
897+
if (objectId == 0)
898+
return ReportErrorAndReturn(fmt::format("invalid attachment object id ({})", objectId).c_str());
899+
900+
GLint componentType = 0;
901+
glGetFramebufferAttachmentParameteriv(target, attachment, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, &componentType);
902+
903+
switch (componentType)
904+
{
905+
case GL_INT:
906+
Impl::ClearBuffer<GLint, &glClearBufferiv>(L, nextArg, bufferType, drawBuffer);
907+
break;
908+
case GL_UNSIGNED_INT:
909+
Impl::ClearBuffer<GLuint, &glClearBufferuiv>(L, nextArg, bufferType, drawBuffer);
910+
break;
911+
case GL_SIGNED_NORMALIZED: [[fallthrough]]; // is this considered a fixed point value?
912+
case GL_UNSIGNED_NORMALIZED: [[fallthrough]]; // is this considered a fixed point value?
913+
case GL_FLOAT:
914+
Impl::ClearBuffer<GLfloat, &glClearBufferfv>(L, nextArg, bufferType, drawBuffer);
915+
break;
916+
default:
917+
return ReportErrorAndReturn(fmt::format("invalid attachment component type ({}), means the attachment is invalid", componentType).c_str());
918+
}
919+
920+
assert(glGetError() == GL_NO_ERROR);
921+
922+
lua_pushboolean(L, true);
923+
return 1;
924+
}
925+
926+
770927
/******************************************************************************/
771928
/******************************************************************************/

rts/Lua/LuaFBOs.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class LuaFBOs {
1818

1919
void Clear() { fbos.clear(); }
2020

21-
struct FBO {
21+
struct LuaFBO {
2222
void Init(lua_State* L);
2323
void Free(lua_State* L);
2424

@@ -31,7 +31,7 @@ class LuaFBOs {
3131
GLsizei zsize;
3232
};
3333

34-
const FBO* GetLuaFBO(lua_State* L, int index);
34+
const LuaFBO* GetLuaFBO(lua_State* L, int index);
3535

3636
public:
3737
static bool PushEntries(lua_State* L);
@@ -45,19 +45,19 @@ class LuaFBOs {
4545
GLenum attachLevel
4646
);
4747
private:
48-
std::vector<FBO*> fbos;
48+
std::vector<LuaFBO*> fbos;
4949

5050
private: // helpers
5151
static bool CreateMetatable(lua_State* L);
5252
static bool AttachObject(
5353
const char* funcName,
5454
lua_State* L, int index,
55-
FBO* fbo, GLenum attachID,
55+
LuaFBO* fbo, GLenum attachID,
5656
GLenum attachTarget = 0,
5757
GLenum attachLevel = 0
5858
);
5959
static bool ApplyAttachment(lua_State* L, int index,
60-
FBO* fbo, GLenum attachID);
60+
LuaFBO* fbo, GLenum attachID);
6161
static bool ApplyDrawBuffers(lua_State* L, int index);
6262

6363
private: // metatable methods
@@ -72,6 +72,7 @@ class LuaFBOs {
7272
static int ActiveFBO(lua_State* L);
7373
static int RawBindFBO(lua_State* L); // unsafe
7474
static int BlitFBO(lua_State* L);
75+
static int ClearAttachmentFBO(lua_State* L);
7576
};
7677

7778

rts/lib/headlessStubs/gladstub.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,9 @@ decltype(glad_glClipControl) glad_glClipControl = nullptr;
512512
decltype(glad_glPushDebugGroup) glad_glPushDebugGroup = nullptr;
513513
decltype(glad_glPopDebugGroup) glad_glPopDebugGroup = nullptr;
514514
decltype(glad_glObjectLabel) glad_glObjectLabel = nullptr;
515+
decltype(glad_glClearBufferuiv) glad_glClearBufferuiv = nullptr;
516+
decltype(glad_glClearBufferiv) glad_glClearBufferiv = nullptr;
517+
decltype(glad_glClearBufferfv) glad_glClearBufferfv = nullptr;
515518

516519
namespace Impl {
517520
template<typename R, typename... Args>
@@ -945,6 +948,9 @@ int gladLoadGL(void) {
945948
glad_glPushDebugGroup = MakeStubImpl(glad_glPushDebugGroup);
946949
glad_glPopDebugGroup = MakeStubImpl(glad_glPopDebugGroup);
947950
glad_glObjectLabel = MakeStubImpl(glad_glObjectLabel);
951+
glad_glClearBufferuiv = MakeStubImpl(glad_glClearBufferuiv);
952+
glad_glClearBufferiv = MakeStubImpl(glad_glClearBufferiv);
953+
glad_glClearBufferfv = MakeStubImpl(glad_glClearBufferfv);
948954

949955
return 0;
950956
}

0 commit comments

Comments
 (0)