mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +00:00
- Added thread safety to texture loading in the software renderer
This commit is contained in:
parent
00f6ed45a2
commit
a663f71a9f
12 changed files with 62 additions and 15 deletions
|
@ -515,6 +515,8 @@ namespace swrenderer
|
||||||
this->rw_pic = pic;
|
this->rw_pic = pic;
|
||||||
this->mask = mask;
|
this->mask = mask;
|
||||||
|
|
||||||
|
Thread->PrepareTexture(pic);
|
||||||
|
|
||||||
if (rw_pic->GetHeight() != 1 << rw_pic->HeightBits)
|
if (rw_pic->GetHeight() != 1 << rw_pic->HeightBits)
|
||||||
{
|
{
|
||||||
ProcessWallNP2(walltop, wallbottom, texturemid, swall, lwall, top, bottom);
|
ProcessWallNP2(walltop, wallbottom, texturemid, swall, lwall, top, bottom);
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
drawerargs.SetSolidColor(3);
|
drawerargs.SetSolidColor(3);
|
||||||
drawerargs.SetTexture(Thread->Viewport.get(), texture);
|
drawerargs.SetTexture(Thread, texture);
|
||||||
|
|
||||||
double planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians();
|
double planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians();
|
||||||
double xstep, ystep, leftxfrac, leftyfrac, rightxfrac, rightyfrac;
|
double xstep, ystep, leftxfrac, leftyfrac, rightxfrac, rightyfrac;
|
||||||
|
|
|
@ -198,8 +198,8 @@ namespace swrenderer
|
||||||
angle1 = (uint32_t)((UMulScale16(ang, frontcyl) + frontpos) >> FRACBITS);
|
angle1 = (uint32_t)((UMulScale16(ang, frontcyl) + frontpos) >> FRACBITS);
|
||||||
angle2 = (uint32_t)((UMulScale16(ang, backcyl) + backpos) >> FRACBITS);
|
angle2 = (uint32_t)((UMulScale16(ang, backcyl) + backpos) >> FRACBITS);
|
||||||
|
|
||||||
drawerargs.SetFrontTexture(viewport, frontskytex, angle1);
|
drawerargs.SetFrontTexture(Thread, frontskytex, angle1);
|
||||||
drawerargs.SetBackTexture(viewport, backskytex, angle2);
|
drawerargs.SetBackTexture(Thread, backskytex, angle2);
|
||||||
drawerargs.SetTextureVStep(uv_step);
|
drawerargs.SetTextureVStep(uv_step);
|
||||||
drawerargs.SetTextureVPos(uv_pos);
|
drawerargs.SetTextureVPos(uv_pos);
|
||||||
drawerargs.SetDest(viewport, start_x, y1);
|
drawerargs.SetDest(viewport, start_x, y1);
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace swrenderer
|
||||||
auto viewport = Thread->Viewport.get();
|
auto viewport = Thread->Viewport.get();
|
||||||
|
|
||||||
drawerargs.SetSolidColor(3);
|
drawerargs.SetSolidColor(3);
|
||||||
drawerargs.SetTexture(Thread->Viewport.get(), texture);
|
drawerargs.SetTexture(Thread, texture);
|
||||||
|
|
||||||
lxscale = _xscale * ifloatpow2[drawerargs.TextureWidthBits()];
|
lxscale = _xscale * ifloatpow2[drawerargs.TextureWidthBits()];
|
||||||
lyscale = _yscale * ifloatpow2[drawerargs.TextureHeightBits()];
|
lyscale = _yscale * ifloatpow2[drawerargs.TextureHeightBits()];
|
||||||
|
|
|
@ -88,4 +88,38 @@ namespace swrenderer
|
||||||
else
|
else
|
||||||
return pal_drawers.get();
|
return pal_drawers.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderThread::PrepareTexture(FTexture *texture)
|
||||||
|
{
|
||||||
|
if (texture == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Textures may not have loaded/refreshed yet. The shared code doing
|
||||||
|
// this is not thread safe. By calling GetPixels in a mutex lock we
|
||||||
|
// make sure that only one thread is loading a texture at any given
|
||||||
|
// time.
|
||||||
|
//
|
||||||
|
// It is critical that this function is called before any direct
|
||||||
|
// calls to GetPixels for this to work.
|
||||||
|
|
||||||
|
static std::mutex loadmutex;
|
||||||
|
loadmutex.lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
texture->GetPixels();
|
||||||
|
const FTexture::Span *spans;
|
||||||
|
texture->GetColumn(0, &spans);
|
||||||
|
if (Viewport->RenderTarget->IsBgra())
|
||||||
|
{
|
||||||
|
texture->GetPixelsBgra();
|
||||||
|
texture->GetColumnBgra(0, &spans);
|
||||||
|
}
|
||||||
|
loadmutex.unlock();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
loadmutex.unlock();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,9 @@ namespace swrenderer
|
||||||
short cliptop[MAXWIDTH];
|
short cliptop[MAXWIDTH];
|
||||||
|
|
||||||
SWPixelFormatDrawers *Drawers(RenderViewport *viewport);
|
SWPixelFormatDrawers *Drawers(RenderViewport *viewport);
|
||||||
|
|
||||||
|
// Make sure texture can accessed safely
|
||||||
|
void PrepareTexture(FTexture *texture);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<SWTruecolorDrawers> tc_drawers;
|
std::unique_ptr<SWTruecolorDrawers> tc_drawers;
|
||||||
|
|
|
@ -274,7 +274,7 @@ void SWCanvas::FillSimplePoly(DCanvas *canvas, FTexture *tex, FVector2 *points,
|
||||||
|
|
||||||
// Setup constant texture mapping parameters.
|
// Setup constant texture mapping parameters.
|
||||||
SpanDrawerArgs drawerargs;
|
SpanDrawerArgs drawerargs;
|
||||||
drawerargs.SetTexture(viewport, tex);
|
drawerargs.SetTexture(&thread, tex);
|
||||||
if (colormap)
|
if (colormap)
|
||||||
drawerargs.SetLight(colormap, 0, clamp(shade >> FRACBITS, 0, NUMCOLORMAPS - 1));
|
drawerargs.SetLight(colormap, 0, clamp(shade >> FRACBITS, 0, NUMCOLORMAPS - 1));
|
||||||
else
|
else
|
||||||
|
|
|
@ -34,9 +34,10 @@ namespace swrenderer
|
||||||
dc_viewport = viewport;
|
dc_viewport = viewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyDrawerArgs::SetFrontTexture(RenderViewport *viewport, FTexture *texture, uint32_t column)
|
void SkyDrawerArgs::SetFrontTexture(RenderThread *thread, FTexture *texture, uint32_t column)
|
||||||
{
|
{
|
||||||
if (viewport->RenderTarget->IsBgra())
|
thread->PrepareTexture(texture);
|
||||||
|
if (thread->Viewport->RenderTarget->IsBgra())
|
||||||
{
|
{
|
||||||
dc_source = (const uint8_t *)texture->GetColumnBgra(column, nullptr);
|
dc_source = (const uint8_t *)texture->GetColumnBgra(column, nullptr);
|
||||||
dc_sourceheight = texture->GetHeight();
|
dc_sourceheight = texture->GetHeight();
|
||||||
|
@ -48,14 +49,15 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyDrawerArgs::SetBackTexture(RenderViewport *viewport, FTexture *texture, uint32_t column)
|
void SkyDrawerArgs::SetBackTexture(RenderThread *thread, FTexture *texture, uint32_t column)
|
||||||
{
|
{
|
||||||
|
thread->PrepareTexture(texture);
|
||||||
if (texture == nullptr)
|
if (texture == nullptr)
|
||||||
{
|
{
|
||||||
dc_source2 = nullptr;
|
dc_source2 = nullptr;
|
||||||
dc_sourceheight2 = 1;
|
dc_sourceheight2 = 1;
|
||||||
}
|
}
|
||||||
else if (viewport->RenderTarget->IsBgra())
|
else if (thread->Viewport->RenderTarget->IsBgra())
|
||||||
{
|
{
|
||||||
dc_source2 = (const uint8_t *)texture->GetColumnBgra(column, nullptr);
|
dc_source2 = (const uint8_t *)texture->GetColumnBgra(column, nullptr);
|
||||||
dc_sourceheight2 = texture->GetHeight();
|
dc_sourceheight2 = texture->GetHeight();
|
||||||
|
|
|
@ -15,8 +15,8 @@ namespace swrenderer
|
||||||
public:
|
public:
|
||||||
void SetDest(RenderViewport *viewport, int x, int y);
|
void SetDest(RenderViewport *viewport, int x, int y);
|
||||||
void SetCount(int count) { dc_count = count; }
|
void SetCount(int count) { dc_count = count; }
|
||||||
void SetFrontTexture(RenderViewport *viewport, FTexture *texture, uint32_t column);
|
void SetFrontTexture(RenderThread *thread, FTexture *texture, uint32_t column);
|
||||||
void SetBackTexture(RenderViewport *viewport, FTexture *texture, uint32_t column);
|
void SetBackTexture(RenderThread *thread, FTexture *texture, uint32_t column);
|
||||||
void SetTextureVPos(uint32_t texturefrac) { dc_texturefrac = texturefrac; }
|
void SetTextureVPos(uint32_t texturefrac) { dc_texturefrac = texturefrac; }
|
||||||
void SetTextureVStep(uint32_t iscale) { dc_iscale = iscale; }
|
void SetTextureVStep(uint32_t iscale) { dc_iscale = iscale; }
|
||||||
void SetSolidTop(uint32_t color) { solid_top = color; }
|
void SetSolidTop(uint32_t color) { solid_top = color; }
|
||||||
|
|
|
@ -22,8 +22,10 @@ namespace swrenderer
|
||||||
spanfunc = &SWPixelFormatDrawers::DrawSpan;
|
spanfunc = &SWPixelFormatDrawers::DrawSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpanDrawerArgs::SetTexture(RenderViewport *viewport, FTexture *tex)
|
void SpanDrawerArgs::SetTexture(RenderThread *thread, FTexture *tex)
|
||||||
{
|
{
|
||||||
|
thread->PrepareTexture(tex);
|
||||||
|
|
||||||
tex->GetWidth();
|
tex->GetWidth();
|
||||||
ds_xbits = tex->WidthBits;
|
ds_xbits = tex->WidthBits;
|
||||||
ds_ybits = tex->HeightBits;
|
ds_ybits = tex->HeightBits;
|
||||||
|
@ -36,7 +38,7 @@ namespace swrenderer
|
||||||
ds_ybits--;
|
ds_ybits--;
|
||||||
}
|
}
|
||||||
|
|
||||||
ds_source = viewport->RenderTarget->IsBgra() ? (const uint8_t*)tex->GetPixelsBgra() : tex->GetPixels();
|
ds_source = thread->Viewport->RenderTarget->IsBgra() ? (const uint8_t*)tex->GetPixelsBgra() : tex->GetPixels();
|
||||||
ds_source_mipmapped = tex->Mipmapped() && tex->GetWidth() > 1 && tex->GetHeight() > 1;
|
ds_source_mipmapped = tex->Mipmapped() && tex->GetWidth() > 1 && tex->GetHeight() > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace swrenderer
|
||||||
void SetDestY(RenderViewport *viewport, int y) { ds_viewport = viewport; ds_y = y; }
|
void SetDestY(RenderViewport *viewport, int y) { ds_viewport = viewport; ds_y = y; }
|
||||||
void SetDestX1(int x) { ds_x1 = x; }
|
void SetDestX1(int x) { ds_x1 = x; }
|
||||||
void SetDestX2(int x) { ds_x2 = x; }
|
void SetDestX2(int x) { ds_x2 = x; }
|
||||||
void SetTexture(RenderViewport *viewport, FTexture *tex);
|
void SetTexture(RenderThread *thread, FTexture *tex);
|
||||||
void SetTextureLOD(double lod) { ds_lod = lod; }
|
void SetTextureLOD(double lod) { ds_lod = lod; }
|
||||||
void SetTextureUPos(dsfixed_t xfrac) { ds_xfrac = xfrac; }
|
void SetTextureUPos(dsfixed_t xfrac) { ds_xfrac = xfrac; }
|
||||||
void SetTextureVPos(dsfixed_t yfrac) { ds_yfrac = yfrac; }
|
void SetTextureVPos(dsfixed_t yfrac) { ds_yfrac = yfrac; }
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace swrenderer
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto viewport = thread->Viewport.get();
|
auto viewport = thread->Viewport.get();
|
||||||
|
|
||||||
// Handle the linear filtered version in a different function to reduce chances of merge conflicts from zdoom.
|
// Handle the linear filtered version in a different function to reduce chances of merge conflicts from zdoom.
|
||||||
if (viewport->RenderTarget->IsBgra() && !drawer_needs_pal_input) // To do: add support to R_DrawColumnHoriz_rgba
|
if (viewport->RenderTarget->IsBgra() && !drawer_needs_pal_input) // To do: add support to R_DrawColumnHoriz_rgba
|
||||||
{
|
{
|
||||||
|
@ -62,6 +62,8 @@ namespace swrenderer
|
||||||
dc_iscale = iscale;
|
dc_iscale = iscale;
|
||||||
dc_textureheight = tex->GetHeight();
|
dc_textureheight = tex->GetHeight();
|
||||||
|
|
||||||
|
thread->PrepareTexture(tex);
|
||||||
|
|
||||||
const FTexture::Span *span;
|
const FTexture::Span *span;
|
||||||
const uint8_t *column;
|
const uint8_t *column;
|
||||||
if (viewport->RenderTarget->IsBgra() && !drawer_needs_pal_input)
|
if (viewport->RenderTarget->IsBgra() && !drawer_needs_pal_input)
|
||||||
|
@ -132,6 +134,8 @@ namespace swrenderer
|
||||||
dc_x = x;
|
dc_x = x;
|
||||||
dc_iscale = iscale;
|
dc_iscale = iscale;
|
||||||
|
|
||||||
|
thread->PrepareTexture(tex);
|
||||||
|
|
||||||
// Normalize to 0-1 range:
|
// Normalize to 0-1 range:
|
||||||
double uv_stepd = FIXED2DBL(dc_iscale);
|
double uv_stepd = FIXED2DBL(dc_iscale);
|
||||||
double v_step = uv_stepd / tex->GetHeight();
|
double v_step = uv_stepd / tex->GetHeight();
|
||||||
|
|
Loading…
Reference in a new issue