Skip to content

Commit

Permalink
Implement gl.ClearBuffer() in a cleaner way
Browse files Browse the repository at this point in the history
  • Loading branch information
lhog committed Feb 16, 2025
1 parent dfe9de2 commit 43986a6
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 23 deletions.
192 changes: 174 additions & 18 deletions rts/Lua/LuaFBOs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "fmt/format.h"

#include "System/Misc/TracyDefs.h"
#include "Rendering/GL/FBO.h"


/******************************************************************************
Expand All @@ -28,7 +29,7 @@
LuaFBOs::~LuaFBOs()
{
RECOIL_DETAILED_TRACY_ZONE;
for (const FBO* fbo: fbos) {
for (const auto* fbo: fbos) {
glDeleteFramebuffersEXT(1, &fbo->id);
}
}
Expand All @@ -48,6 +49,9 @@ bool LuaFBOs::PushEntries(lua_State* L)
REGISTER_LUA_CFUNC(ActiveFBO);
REGISTER_LUA_CFUNC(RawBindFBO);

if (GLAD_GL_VERSION_3_0)
REGISTER_LUA_CFUNC(ClearAttachmentFBO);

if (GLAD_GL_EXT_framebuffer_blit)
REGISTER_LUA_CFUNC(BlitFBO);

Expand Down Expand Up @@ -128,17 +132,17 @@ static GLenum ParseAttachment(const std::string& name)
/******************************************************************************/
/******************************************************************************/

const LuaFBOs::FBO* LuaFBOs::GetLuaFBO(lua_State* L, int index)
const LuaFBOs::LuaFBO* LuaFBOs::GetLuaFBO(lua_State* L, int index)
{
RECOIL_DETAILED_TRACY_ZONE;
return static_cast<FBO*>(LuaUtils::GetUserData(L, index, "FBO"));
return static_cast<LuaFBO*>(LuaUtils::GetUserData(L, index, "FBO"));
}


/******************************************************************************/
/******************************************************************************/

void LuaFBOs::FBO::Init(lua_State* L)
void LuaFBOs::LuaFBO::Init(lua_State* L)
{
RECOIL_DETAILED_TRACY_ZONE;
index = -1u;
Expand All @@ -151,7 +155,7 @@ void LuaFBOs::FBO::Init(lua_State* L)
}


void LuaFBOs::FBO::Free(lua_State* L)
void LuaFBOs::LuaFBO::Free(lua_State* L)
{
RECOIL_DETAILED_TRACY_ZONE;
if (luaRef == LUA_NOREF)
Expand Down Expand Up @@ -184,7 +188,7 @@ void LuaFBOs::FBO::Free(lua_State* L)
int LuaFBOs::meta_gc(lua_State* L)
{
RECOIL_DETAILED_TRACY_ZONE;
FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
fbo->Free(L);
return 0;
}
Expand All @@ -193,7 +197,7 @@ int LuaFBOs::meta_gc(lua_State* L)
int LuaFBOs::meta_index(lua_State* L)
{
RECOIL_DETAILED_TRACY_ZONE;
const FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
const auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));

if (fbo->luaRef == LUA_NOREF)
return 0;
Expand All @@ -209,7 +213,7 @@ int LuaFBOs::meta_index(lua_State* L)
int LuaFBOs::meta_newindex(lua_State* L)
{
RECOIL_DETAILED_TRACY_ZONE;
FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));

if (fbo->luaRef == LUA_NOREF)
return 0;
Expand Down Expand Up @@ -264,7 +268,7 @@ bool LuaFBOs::AttachObject(
const char* funcName,
lua_State* L,
int index,
FBO* fbo,
LuaFBO* fbo,
GLenum attachID,
GLenum attachTarget,
GLenum attachLevel
Expand Down Expand Up @@ -353,7 +357,7 @@ void LuaFBOs::AttachObjectTexTarget(const char* funcName, GLenum fboTarget, GLen
bool LuaFBOs::ApplyAttachment(
lua_State* L,
int index,
FBO* fbo,
LuaFBO* fbo,
const GLenum attachID
) {
RECOIL_DETAILED_TRACY_ZONE;
Expand Down Expand Up @@ -437,7 +441,7 @@ bool LuaFBOs::ApplyDrawBuffers(lua_State* L, int index)
*/
int LuaFBOs::CreateFBO(lua_State* L)
{
FBO fbo;
LuaFBO fbo;
fbo.Init(L);

const int table = 1;
Expand Down Expand Up @@ -468,7 +472,7 @@ int LuaFBOs::CreateFBO(lua_State* L)
glBindFramebufferEXT(fbo.target, fbo.id);


FBO* fboPtr = static_cast<FBO*>(lua_newuserdata(L, sizeof(FBO)));
auto* fboPtr = static_cast<LuaFBO*>(lua_newuserdata(L, sizeof(LuaFBO)));
*fboPtr = fbo;

luaL_getmetatable(L, "FBO");
Expand Down Expand Up @@ -517,7 +521,7 @@ int LuaFBOs::DeleteFBO(lua_State* L)
if (lua_isnil(L, 1))
return 0;

FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
fbo->Free(L);
return 0;
}
Expand All @@ -537,7 +541,7 @@ int LuaFBOs::IsValidFBO(lua_State* L)
return 1;
}

const FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
const auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));

if ((fbo->id == 0) || (fbo->luaRef == LUA_NOREF)) {
lua_pushboolean(L, false);
Expand Down Expand Up @@ -580,7 +584,7 @@ int LuaFBOs::ActiveFBO(lua_State* L)
RECOIL_DETAILED_TRACY_ZONE;
CheckDrawingEnabled(L, __func__);

const FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
const auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));

if (fbo->id == 0)
return 0;
Expand Down Expand Up @@ -664,7 +668,7 @@ int LuaFBOs::RawBindFBO(lua_State* L)
return 0;
}

const FBO* fbo = static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
const auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));

if (fbo->id == 0)
return 0;
Expand Down Expand Up @@ -731,8 +735,8 @@ int LuaFBOs::BlitFBO(lua_State* L)
return 0;
}

const FBO* fboSrc = (lua_isnil(L, 1))? nullptr: static_cast<FBO*>(luaL_checkudata(L, 1, "FBO"));
const FBO* fboDst = (lua_isnil(L, 6))? nullptr: static_cast<FBO*>(luaL_checkudata(L, 6, "FBO"));
const auto* fboSrc = (lua_isnil(L, 1))? nullptr: static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
const auto* fboDst = (lua_isnil(L, 6))? nullptr: static_cast<LuaFBO*>(luaL_checkudata(L, 6, "FBO"));

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


namespace Impl {
template<class Type, auto glClearBufferFuncPtr>
static inline void ClearBuffer(lua_State* L, int startIdx, GLenum bufferType, GLint drawBuffer) {
Type values[4];
values[0] = spring::SafeCast<Type>(luaL_optnumber(L, startIdx + 0, 0));
values[1] = spring::SafeCast<Type>(luaL_optnumber(L, startIdx + 1, 0));
values[2] = spring::SafeCast<Type>(luaL_optnumber(L, startIdx + 2, 0));
values[3] = spring::SafeCast<Type>(luaL_optnumber(L, startIdx + 3, 0));
(*glClearBufferFuncPtr)(bufferType, drawBuffer, values);
}
}

/*** needs `GL_VERSION_3_0`
*
* @function gl.ClearAttachmentFBO
* @param fbo Fbo|nil (nil for currently bound FBO)
* @param target number? (GL.FRAMEBUFFER default)
* @param attachment number|text
* @param clearValue0 number
* @param clearValue1 number
* @param clearValue2 number
* @param clearValue3 number
*/

int LuaFBOs::ClearAttachmentFBO(lua_State* L)
{
GLenum fboID = 0;
if (lua_isnil(L, 1))
fboID = FBO::GetCurrentBoundFBO();
else if (lua_isuserdata(L, 1)) {
const auto* fbo = static_cast<LuaFBO*>(luaL_checkudata(L, 1, "FBO"));
fboID = fbo->id;
if (fbo->luaRef == LUA_NOREF) {
lua_pushboolean(L, false);
return 1;
}
}
else {
lua_pushboolean(L, false);
return 1;
}

GLenum target = luaL_optint(L, 2, GL_FRAMEBUFFER);
switch (target)
{
case GL_DRAW_FRAMEBUFFER: [[fallthrough]];
case GL_READ_FRAMEBUFFER: [[fallthrough]];
case GL_FRAMEBUFFER: [[fallthrough]];
default: {
lua_pushboolean(L, false);
return 1;
}
}

GLenum bufferType;
GLenum attachment;
GLenum drawBuffer;

if (lua_isstring(L, 3)) {
switch (hashString(luaL_checkstring(L, 3))) {
case hashString("color0"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT0; drawBuffer = 0; } break;
case hashString("color1"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT1; drawBuffer = 1; } break;
case hashString("color2"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT2; drawBuffer = 2; } break;
case hashString("color3"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT3; drawBuffer = 3; } break;
case hashString("color4"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT4; drawBuffer = 4; } break;
case hashString("color5"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT5; drawBuffer = 5; } break;
case hashString("color6"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT6; drawBuffer = 6; } break;
case hashString("color7"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT7; drawBuffer = 7; } break;
case hashString("color8"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT8; drawBuffer = 8; } break;
case hashString("color9"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT9; drawBuffer = 9; } break;
case hashString("color10"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT10; drawBuffer = 10; } break;
case hashString("color11"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT11; drawBuffer = 11; } break;
case hashString("color12"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT12; drawBuffer = 12; } break;
case hashString("color13"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT13; drawBuffer = 13; } break;
case hashString("color14"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT14; drawBuffer = 14; } break;
case hashString("color15"): { bufferType = GL_COLOR; attachment = GL_COLOR_ATTACHMENT15; drawBuffer = 15; } break;
case hashString("depth"): { bufferType = GL_DEPTH; attachment = GL_DEPTH_ATTACHMENT; drawBuffer = 0; } break;
case hashString("stencil"): { bufferType = GL_STENCIL; attachment = GL_STENCIL_ATTACHMENT; drawBuffer = 0; } break;
default: {
lua_pushboolean(L, false);
return 1;
} break;
}
}
else if (lua_isnumber(L, 3)) {
switch (attachment = luaL_checkint(L, 3)) {
case GL_COLOR_ATTACHMENT0: { bufferType = GL_COLOR; drawBuffer = 0; } break;
case GL_COLOR_ATTACHMENT1: { bufferType = GL_COLOR; drawBuffer = 1; } break;
case GL_COLOR_ATTACHMENT2: { bufferType = GL_COLOR; drawBuffer = 2; } break;
case GL_COLOR_ATTACHMENT3: { bufferType = GL_COLOR; drawBuffer = 3; } break;
case GL_COLOR_ATTACHMENT4: { bufferType = GL_COLOR; drawBuffer = 4; } break;
case GL_COLOR_ATTACHMENT5: { bufferType = GL_COLOR; drawBuffer = 5; } break;
case GL_COLOR_ATTACHMENT6: { bufferType = GL_COLOR; drawBuffer = 6; } break;
case GL_COLOR_ATTACHMENT7: { bufferType = GL_COLOR; drawBuffer = 7; } break;
case GL_COLOR_ATTACHMENT8: { bufferType = GL_COLOR; drawBuffer = 8; } break;
case GL_COLOR_ATTACHMENT9: { bufferType = GL_COLOR; drawBuffer = 9; } break;
case GL_COLOR_ATTACHMENT10: { bufferType = GL_COLOR; drawBuffer = 10; } break;
case GL_COLOR_ATTACHMENT11: { bufferType = GL_COLOR; drawBuffer = 11; } break;
case GL_COLOR_ATTACHMENT12: { bufferType = GL_COLOR; drawBuffer = 12; } break;
case GL_COLOR_ATTACHMENT13: { bufferType = GL_COLOR; drawBuffer = 13; } break;
case GL_COLOR_ATTACHMENT14: { bufferType = GL_COLOR; drawBuffer = 14; } break;
case GL_COLOR_ATTACHMENT15: { bufferType = GL_COLOR; drawBuffer = 15; } break;
case GL_DEPTH_ATTACHMENT: { bufferType = GL_DEPTH; drawBuffer = 0; } break;
case GL_STENCIL_ATTACHMENT: { bufferType = GL_STENCIL; drawBuffer = 0; } break;
default: {
lua_pushboolean(L, false);
return 1;
} break;
}
}

GLint attachmentType = GL_NONE;
glGetFramebufferAttachmentParameteriv(target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &attachmentType);

if (attachmentType == GL_NONE || attachmentType == GL_FRAMEBUFFER_DEFAULT) {
lua_pushboolean(L, false);
return 1;
}

GLint objectId = 0;
glGetFramebufferAttachmentParameteriv(target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &objectId);
if (objectId == 0) {
lua_pushboolean(L, false);
return 1;
}

GLint componentType = 0;
glGetFramebufferAttachmentParameteriv(target, attachment, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, &componentType);

switch (componentType)
{
case GL_INT:
Impl::ClearBuffer<GLint, &glClearBufferiv>(L, 4, bufferType, drawBuffer);
break;
case GL_UNSIGNED_INT:
Impl::ClearBuffer<GLuint, &glClearBufferuiv>(L, 4, bufferType, drawBuffer);
break;
case GL_SIGNED_NORMALIZED: [[fallthrough]]; // is this considered a fixed point value?
case GL_UNSIGNED_NORMALIZED: [[fallthrough]]; // is this considered a fixed point value?
case GL_FLOAT:
Impl::ClearBuffer<GLfloat, &glClearBufferfv>(L, 4, bufferType, drawBuffer);
break;
default:
lua_pushboolean(L, false);
return 1;
}

lua_pushboolean(L, true);
return 1;
}


/******************************************************************************/
/******************************************************************************/
11 changes: 6 additions & 5 deletions rts/Lua/LuaFBOs.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class LuaFBOs {

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

struct FBO {
struct LuaFBO {
void Init(lua_State* L);
void Free(lua_State* L);

Expand All @@ -31,7 +31,7 @@ class LuaFBOs {
GLsizei zsize;
};

const FBO* GetLuaFBO(lua_State* L, int index);
const LuaFBO* GetLuaFBO(lua_State* L, int index);

public:
static bool PushEntries(lua_State* L);
Expand All @@ -45,19 +45,19 @@ class LuaFBOs {
GLenum attachLevel
);
private:
std::vector<FBO*> fbos;
std::vector<LuaFBO*> fbos;

private: // helpers
static bool CreateMetatable(lua_State* L);
static bool AttachObject(
const char* funcName,
lua_State* L, int index,
FBO* fbo, GLenum attachID,
LuaFBO* fbo, GLenum attachID,
GLenum attachTarget = 0,
GLenum attachLevel = 0
);
static bool ApplyAttachment(lua_State* L, int index,
FBO* fbo, GLenum attachID);
LuaFBO* fbo, GLenum attachID);
static bool ApplyDrawBuffers(lua_State* L, int index);

private: // metatable methods
Expand All @@ -72,6 +72,7 @@ class LuaFBOs {
static int ActiveFBO(lua_State* L);
static int RawBindFBO(lua_State* L); // unsafe
static int BlitFBO(lua_State* L);
static int ClearAttachmentFBO(lua_State* L);
};


Expand Down

0 comments on commit 43986a6

Please sign in to comment.