mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-11 07:11:39 +00:00
Lunatic: working tsprite methods, static members, struct array timing test.
git-svn-id: https://svn.eduke32.com/eduke32@3468 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
1dd52a4d6e
commit
90793f6a67
3 changed files with 190 additions and 34 deletions
|
@ -11,6 +11,7 @@ ffi.cdef "enum { _DEBUG_LUNATIC=1 }"
|
|||
|
||||
local bit = require("bit")
|
||||
local string = require("string")
|
||||
local table = require("table")
|
||||
|
||||
local assert = assert
|
||||
local error = error
|
||||
|
@ -103,8 +104,9 @@ end
|
|||
ffi.cdef([[
|
||||
typedef $ sectortype;
|
||||
typedef $ walltype;
|
||||
// NOTE: spritetype and tspritetype are different types with the same data members.
|
||||
typedef $ spritetype;
|
||||
typedef $ tspritetype;
|
||||
typedef struct { spritetype; } tspritetype;
|
||||
|
||||
typedef struct {
|
||||
const uint32_t mdanimtims;
|
||||
|
@ -132,9 +134,7 @@ typedef struct {
|
|||
} hitdata_t;
|
||||
]],
|
||||
ffi.typeof(SECTOR_STRUCT), ffi.typeof(WALL_STRUCT),
|
||||
ffi.typeof(SPRITE_STRUCT), ffi.typeof(SPRITE_STRUCT))
|
||||
-- NOTE: spritetype and tspritetype are different types with the same layout.
|
||||
-- (XXX: is there a better way?)
|
||||
ffi.typeof(SPRITE_STRUCT))
|
||||
|
||||
-- Define the "palette_t" type, which for us has .{r,g,b} fields and a
|
||||
-- bound-checking array of length 3 overlaid.
|
||||
|
@ -337,6 +337,12 @@ local sectortype_mt = {
|
|||
}
|
||||
ffi.metatype("sectortype", sectortype_mt)
|
||||
|
||||
local band = bit.band
|
||||
local bor = bit.bor
|
||||
local bnot = bit.bnot
|
||||
local lshift = bit.lshift
|
||||
local rshift = bit.rshift
|
||||
|
||||
local walltype_ptr_ct = ffi.typeof("$ *", ffi.typeof(strip_const(WALL_STRUCT)))
|
||||
|
||||
local walltype_mt = {
|
||||
|
@ -366,19 +372,19 @@ local walltype_mt = {
|
|||
|
||||
--- Predicates
|
||||
isblocking = function(w)
|
||||
return (bit.band(w.cstat, 1)~=0)
|
||||
return (band(w.cstat, 1)~=0)
|
||||
end,
|
||||
|
||||
ismasked = function(w)
|
||||
return (bit.band(w.cstat, 16)~=0)
|
||||
return (band(w.cstat, 16)~=0)
|
||||
end,
|
||||
|
||||
isoneway = function(w)
|
||||
return (bit.band(w.cstat, 32)~=0)
|
||||
return (band(w.cstat, 32)~=0)
|
||||
end,
|
||||
|
||||
ishittable = function(w)
|
||||
return (bit.band(w.cstat, 64)~=0)
|
||||
return (band(w.cstat, 64)~=0)
|
||||
end,
|
||||
}
|
||||
}
|
||||
|
@ -388,13 +394,15 @@ local spriteext_mt = {
|
|||
__index = {
|
||||
-- Enable EVENT_ANIMATESPRITES for this sprite.
|
||||
make_animated = function(sx)
|
||||
sx.flags = bit.bor(sx.flags, 16)
|
||||
sx.flags = bor(sx.flags, 16)
|
||||
end,
|
||||
},
|
||||
}
|
||||
ffi.metatype("spriteext_t", spriteext_mt)
|
||||
|
||||
local spritetype_ptr_ct = ffi.typeof("$ *", ffi.typeof(strip_const(SPRITE_STRUCT)))
|
||||
-- NOTE: this is the *protected* tspritetype pointer.
|
||||
local tspritetype_ptr_ct = ffi.typeof("$ *", ffi.typeof("tspritetype"))
|
||||
|
||||
local spritetype_mt = {
|
||||
__pow = function(s, zofs)
|
||||
|
@ -412,6 +420,15 @@ local spritetype_mt = {
|
|||
-- XXX: for now, no checking
|
||||
ffi.cast(spritetype_ptr_ct, s).yvel = yvel
|
||||
end,
|
||||
|
||||
--- Custom setters
|
||||
set_cstat_bits = function(s, bits)
|
||||
s.cstat = bor(s.cstat, bits)
|
||||
end,
|
||||
|
||||
clear_cstat_bits = function(s, bits)
|
||||
s.cstat = band(s.cstat, bnot(bits))
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -430,20 +447,29 @@ end
|
|||
|
||||
local tspritetype_mt = deep_copy(spritetype_mt)
|
||||
|
||||
print(spritetype_mt)
|
||||
print(spritetype_mt.__index)
|
||||
print(tspritetype_mt)
|
||||
print(tspritetype_mt.__index)
|
||||
|
||||
-- Methods that are specific to tsprites
|
||||
-- XXX: doesn't work with LuaJIT git f772bed34b39448e3a9ab8d07f6d5c0c26300e1b
|
||||
function tspritetype_mt.__index.dup(tspr)
|
||||
if (ffiC.spritesortcnt >= ffiC.MAXSPRITESONSCREEN+0ULL) then
|
||||
return nil
|
||||
end
|
||||
|
||||
local newtspr = ffi.tsprite[ffiC.spritesortcnt]
|
||||
local newtspr = ffiC.tsprite[ffiC.spritesortcnt]
|
||||
ffi.copy(newtspr, tspr, ffi.sizeof(tspr))
|
||||
ffiC.spritesortcnt = ffiC.spritesortcnt+1
|
||||
|
||||
return newtspr
|
||||
end
|
||||
|
||||
function tspritetype_mt.__index.getspr(tspr)
|
||||
return sprite[tspr.owner]
|
||||
end
|
||||
|
||||
|
||||
-- The user of this module can insert additional "spritetype" index
|
||||
-- methods and register them with "ffi.metatype".
|
||||
function finish_spritetype(mt_index)
|
||||
|
@ -465,29 +491,76 @@ function setmtonce(tab, mt)
|
|||
end
|
||||
|
||||
---- indirect C array access ----
|
||||
local sector_mt = {
|
||||
__index = function(tab, key)
|
||||
if (key >= 0 and key < ffiC.numsectors) then return ffiC.sector[key] end
|
||||
error('out-of-bounds sector[] read access', 2)
|
||||
end,
|
||||
|
||||
__newindex = function() error('cannot write directly to sector[]', 2) end,
|
||||
-- Construct const struct from table
|
||||
local function conststruct(tab)
|
||||
local strtab = { "const struct { int32_t " }
|
||||
local vals = {}
|
||||
|
||||
for member, val in pairs(tab) do
|
||||
strtab[#strtab+1] = member..","
|
||||
vals[#vals+1] = val
|
||||
end
|
||||
strtab[#strtab] = strtab[#strtab]:gsub(',',';')
|
||||
strtab[#strtab+1] = "}"
|
||||
|
||||
return ffi.new(table.concat(strtab), vals)
|
||||
end
|
||||
|
||||
-- Static, non-instance members. Used to hold constants, for example
|
||||
-- sprite.CSTAT.TRANSLUCENT1
|
||||
local static_members = { sector={}, wall={}, sprite={} }
|
||||
|
||||
static_members.sector.STAT = conststruct
|
||||
{
|
||||
MASKED = 128,
|
||||
-- NOTE the reversed order
|
||||
TRANSLUCENT2 = 128,
|
||||
TRANSLUCENT1 = 256,
|
||||
TRANSLUCENT_BOTH_BITS = 256+128,
|
||||
}
|
||||
|
||||
local wall_mt = {
|
||||
__index = function(tab, key)
|
||||
if (key >= 0 and key < ffiC.numwalls) then return ffiC.wall[key] end
|
||||
error('out-of-bounds wall[] read access', 2)
|
||||
end,
|
||||
|
||||
__newindex = function() error('cannot write directly to wall[]', 2) end,
|
||||
static_members.wall.CSTAT = conststruct
|
||||
{
|
||||
MASKED = 64,
|
||||
TRANSLUCENT1 = 128,
|
||||
TRANSLUCENT2 = 512,
|
||||
TRANSLUCENT_BOTH_BITS = 512+128,
|
||||
}
|
||||
|
||||
static_members.sprite.CSTAT = conststruct
|
||||
{
|
||||
TRANSLUCENT1 = 2,
|
||||
TRANSLUCENT2 = 512,
|
||||
TRANSLUCENT_BOTH_BITS = 512+2,
|
||||
}
|
||||
|
||||
local function GenStructMetatable(Structname, Boundname)
|
||||
return {
|
||||
__index = function(tab, key)
|
||||
if (type(key)=="number") then
|
||||
if (key >= 0 and key < ffiC[Boundname]) then
|
||||
return ffiC[Structname][key]
|
||||
end
|
||||
error("out-of-bounds "..Structname.."[] read access", 2)
|
||||
elseif (type(key)=="string") then
|
||||
return static_members[Structname][key]
|
||||
end
|
||||
end,
|
||||
|
||||
__newindex = function() error("cannot write directly to "..Structname.."[]", 2) end,
|
||||
}
|
||||
end
|
||||
|
||||
local sector_mt = GenStructMetatable("sector", "numsectors")
|
||||
local wall_mt = GenStructMetatable("wall", "numwalls")
|
||||
local sprite_mt = GenStructMetatable("sprite", "MAXSPRITES")
|
||||
|
||||
local atsprite_mt = {
|
||||
__index = function(tab, idx)
|
||||
check_sprite_idx(idx)
|
||||
|
||||
local tspr = ffi.cast(spritetype_ptr_ct, ffiC.spriteext[idx]._tspr)
|
||||
local tspr = ffi.cast(tspritetype_ptr_ct, ffiC.spriteext[idx]._tspr)
|
||||
if (tspr == nil) then
|
||||
error("tsprite of actor "..idx.." unavailable", 2)
|
||||
end
|
||||
|
@ -530,7 +603,7 @@ end
|
|||
|
||||
sector = setmtonce({}, sector_mt)
|
||||
wall = setmtonce({}, wall_mt)
|
||||
sprite = creategtab(ffiC.sprite, ffiC.MAXSPRITES, 'sprite[]')
|
||||
sprite = setmtonce({}, sprite_mt)
|
||||
spriteext = creategtab(ffiC.spriteext, ffiC.MAXSPRITES, 'spriteext[]')
|
||||
atsprite = setmtonce({}, atsprite_mt)
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ checkfail('gv.sprite[0].yrepeat = 100', "access forbidden")
|
|||
-- indexing struct array with non-numeric type
|
||||
checkfail('local i = sprite["qwe"]') -- this will produce an error inside the sprite metatable
|
||||
|
||||
checkfail('print(sprite[100000].ceilingpal)', "out-of-bounds sprite[] struct read access")
|
||||
checkfail('print(sprite[100000].ceilingpal)', "out-of-bounds sprite[] read access")
|
||||
|
||||
checkfail('print(gv.sprite[0])', "access forbidden")
|
||||
|
||||
|
@ -186,9 +186,9 @@ checkfail("do local bt=require'bittest'; bt.QWE=1; end", "modifying module table
|
|||
-- the cdata returned by player[] can't be made into a pointer!
|
||||
checkfail("do local pl=player[0]; i=pl[1]; end")
|
||||
checkfail("do local ud=gv.ud.camerasprite; end", "access forbidden") -- test for proper decl()
|
||||
checkfail("sprite[0]:set_picnum(-10)", "attempt to set invalid picnum")
|
||||
checkfail("sprite[0]:set_picnum(-10)", "invalid tile number")
|
||||
checkfail("gv.g_sizes_of=nil; print(gv.g_sizes_of[0])", "write access forbidden")
|
||||
checkfail("gv.cam.sect=-1", "passed out-of-bounds sector number")
|
||||
checkfail("gv.cam.sect=-1", "invalid sector number")
|
||||
|
||||
printf('ceilingbunch of sector 0: %d', getbunch(0, gv.CEILING))
|
||||
|
||||
|
@ -266,6 +266,29 @@ gameevent(gv.EVENT_ENTERLEVEL,
|
|||
player[0].weapon.SHOTGUN.shoots = 1653
|
||||
projectile[1653].drop = 0
|
||||
|
||||
t = gv.gethitickms()
|
||||
local N=1
|
||||
for n=1,N do
|
||||
for i=0,gv.MAXSPRITES-1 do
|
||||
sprite[i].filler = 1
|
||||
end
|
||||
for i=gv.MAXSPRITES-1,0,-1 do
|
||||
sprite[i].shade = 1
|
||||
end
|
||||
for i=0,gv.MAXSPRITES-1 do
|
||||
sprite[i].xoffset = 0
|
||||
end
|
||||
for i=gv.MAXSPRITES-1,0,-1 do
|
||||
sprite[i].yoffset = 1
|
||||
end
|
||||
end
|
||||
t = gv.gethitickms()-t
|
||||
printf("%d x four 0..MAXSPRITES-1 iterations took %.03f us per outer iteration", N, (1000*t)/N)
|
||||
-- Results on x86:
|
||||
-- N=1: 480-1000 us (too large variance)
|
||||
-- N=10: 190-210 us * 10 = 1.9-2.1 ms
|
||||
-- N=100: about 160 us * 100 = about 16 ms
|
||||
|
||||
checkfail("gameevent('GAME', function() print('qwe') end)",
|
||||
"must be called from top level")
|
||||
end
|
||||
|
@ -327,15 +350,18 @@ gameevent("DISPLAYROOMS",
|
|||
end
|
||||
)
|
||||
|
||||
local CS = sprite.CSTAT
|
||||
|
||||
gameevent("ANIMATESPRITES",
|
||||
function(aci)
|
||||
local tspr = atsprite[aci]
|
||||
if (tspr.picnum==1680) then
|
||||
--[[
|
||||
if (tspr:getspr().picnum==1680) then
|
||||
local tspr2 = tspr:dup()
|
||||
tspr2.x = tspr2.x + 512*math.cos(gv.totalclock/120)
|
||||
tspr2.y = tspr2.y + 512*math.sin(gv.totalclock/120)
|
||||
--]]
|
||||
if (tspr2) then
|
||||
tspr2.x = tspr2.x + 512*math.cos(gv.totalclock/60)
|
||||
tspr2.y = tspr2.y + 512*math.sin(gv.totalclock/60)
|
||||
tspr2:set_cstat_bits(CS.TRANSLUCENT_BOTH_BITS)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
57
polymer/eduke32/source/lunatic/test/sprite_access.con
Normal file
57
polymer/eduke32/source/lunatic/test/sprite_access.con
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Timing test for four 0..MAXSPRITES-1 access loops,
|
||||
// fwd->back->fwd->back.
|
||||
// Results with a LTO=1 RELEASE=1 C-CON build on x86: 42 ms for N=10.
|
||||
// (Compare with Lunatic results in test.elua)
|
||||
|
||||
define N 10
|
||||
gamevar n 0 0
|
||||
gamevar i 0 0
|
||||
gamevar t 0 0
|
||||
gamevar t2 0 0
|
||||
define MAXSPRITES 16384
|
||||
define MAXSPRM1 16383 // MAXSPRITES-1
|
||||
|
||||
onevent EVENT_ENTERLEVEL
|
||||
getticks t
|
||||
|
||||
setvar n 0
|
||||
whilevarn n N
|
||||
{
|
||||
setvar i 0
|
||||
whilevarvarn i MAXSPRITES
|
||||
{
|
||||
setactor[i].detail 1
|
||||
addvar i 1
|
||||
}
|
||||
|
||||
setvar i MAXSPRM1
|
||||
whilevarvarn i -1
|
||||
{
|
||||
setactor[i].shade 1
|
||||
subvar i 1
|
||||
}
|
||||
|
||||
setvar i 0
|
||||
whilevarvarn i MAXSPRITES
|
||||
{
|
||||
setactor[i].xoffset 0
|
||||
addvar i 1
|
||||
}
|
||||
|
||||
setvar i MAXSPRM1
|
||||
whilevarvarn i -1
|
||||
{
|
||||
setactor[i].yoffset 0
|
||||
subvar i 1
|
||||
}
|
||||
|
||||
addvar n 1
|
||||
}
|
||||
|
||||
getticks t2
|
||||
subvarvar t2 t
|
||||
|
||||
redefinequote 114 %d x four 0..MAXSPITES-1 iterations took %d ms in total
|
||||
qsprintf 115 114 n t2
|
||||
echo 115
|
||||
endevent
|
Loading…
Reference in a new issue