mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
- change the software renderer to render to a DSimpleCanvas like the old D3D9 target did. Then use the drawer threads to memcpy the result to the PBO
This commit is contained in:
parent
4d35b12808
commit
a841602d70
15 changed files with 70 additions and 28 deletions
|
@ -296,10 +296,7 @@ void FHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
|
|||
{
|
||||
glGenBuffers(1, &glBufferID);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBufferID);
|
||||
if (screen->hwcaps & RFL_BUFFER_STORAGE)
|
||||
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, w*h*texelsize, nullptr, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_CLIENT_STORAGE_BIT);
|
||||
else
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, w*h*texelsize, nullptr, GL_STREAM_DRAW);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, w*h*texelsize, nullptr, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
@ -308,16 +305,7 @@ void FHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
|
|||
uint8_t *FHardwareTexture::MapBuffer()
|
||||
{
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBufferID);
|
||||
if (screen->hwcaps & RFL_BUFFER_STORAGE)
|
||||
{
|
||||
GLint size = -1;
|
||||
glGetBufferParameteriv(GL_PIXEL_UNPACK_BUFFER, GL_BUFFER_SIZE, &size);
|
||||
return (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (uint8_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);
|
||||
}
|
||||
return (uint8_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -169,6 +169,7 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs, const vo
|
|||
args.uniforms = &drawargs;
|
||||
args.destBgra = dest_bgra;
|
||||
args.stencilbuffer = PolyStencilBuffer::Instance()->Values();
|
||||
args.stencilpitch = PolyStencilBuffer::Instance()->Width();
|
||||
args.zbuffer = PolyZBuffer::Instance()->Values();
|
||||
args.depthOffset = weaponScene ? 1.0f : 0.0f;
|
||||
|
||||
|
@ -222,6 +223,7 @@ void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void
|
|||
args.uniforms = &drawargs;
|
||||
args.destBgra = dest_bgra;
|
||||
args.stencilbuffer = PolyStencilBuffer::Instance()->Values();
|
||||
args.stencilpitch = PolyStencilBuffer::Instance()->Width();
|
||||
args.zbuffer = PolyZBuffer::Instance()->Values();
|
||||
args.depthOffset = weaponScene ? 1.0f : 0.0f;
|
||||
|
||||
|
|
|
@ -153,8 +153,8 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat
|
|||
int x = leftEdge[y];
|
||||
int xend = rightEdge[y];
|
||||
|
||||
float *zbufferLine = args->zbuffer + args->pitch * y;
|
||||
uint8_t *stencilLine = args->stencilbuffer + args->pitch * y;
|
||||
float *zbufferLine = args->zbuffer + args->stencilpitch * y;
|
||||
uint8_t *stencilLine = args->stencilbuffer + args->stencilpitch * y;
|
||||
|
||||
float startX = x + (0.5f - v1X);
|
||||
float startY = y + (0.5f - v1Y);
|
||||
|
|
|
@ -53,6 +53,7 @@ struct TriDrawTriangleArgs
|
|||
int32_t clipright;
|
||||
int32_t clipbottom;
|
||||
uint8_t *stencilbuffer;
|
||||
int stencilpitch;
|
||||
float *zbuffer;
|
||||
const PolyDrawArgs *uniforms;
|
||||
bool destBgra;
|
||||
|
|
|
@ -58,7 +58,7 @@ PolyRenderer::PolyRenderer()
|
|||
{
|
||||
}
|
||||
|
||||
void PolyRenderer::RenderView(player_t *player, DCanvas *target)
|
||||
void PolyRenderer::RenderView(player_t *player, DCanvas *target, void *videobuffer)
|
||||
{
|
||||
using namespace swrenderer;
|
||||
|
||||
|
@ -70,6 +70,11 @@ void PolyRenderer::RenderView(player_t *player, DCanvas *target)
|
|||
RenderActorView(player->mo, false);
|
||||
|
||||
Threads.MainThread()->FlushDrawQueue();
|
||||
|
||||
auto copyqueue = std::make_shared<DrawerCommandQueue>(Threads.MainThread()->FrameMemory.get());
|
||||
copyqueue->Push<MemcpyCommand>(videobuffer, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1);
|
||||
DrawerThreads::Execute(copyqueue);
|
||||
|
||||
PolyDrawerWaitCycles.Clock();
|
||||
DrawerThreads::WaitForWorkers();
|
||||
PolyDrawerWaitCycles.Unclock();
|
||||
|
|
|
@ -49,7 +49,7 @@ class PolyRenderer
|
|||
public:
|
||||
PolyRenderer();
|
||||
|
||||
void RenderView(player_t *player, DCanvas *target);
|
||||
void RenderView(player_t *player, DCanvas *target, void *videobuffer);
|
||||
void RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines);
|
||||
void RenderRemainingPlayerSprites();
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ struct FRenderer
|
|||
virtual void Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitlist) = 0;
|
||||
|
||||
// render 3D view
|
||||
virtual void RenderView(player_t *player, DCanvas *target) = 0;
|
||||
virtual void RenderView(player_t *player, DCanvas *target, void *videobuffer) = 0;
|
||||
|
||||
// renders view to a savegame picture
|
||||
virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height) = 0;
|
||||
|
|
|
@ -223,3 +223,27 @@ void GroupMemoryBarrierCommand::Execute(DrawerThread *thread)
|
|||
condition.notify_all();
|
||||
condition.wait(lock, [&]() { return count >= (size_t)thread->num_cores; });
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MemcpyCommand::MemcpyCommand(void *dest, const void *src, int width, int height, int srcpitch, int pixelsize)
|
||||
: dest(dest), src(src), width(width), height(height), srcpitch(srcpitch), pixelsize(pixelsize)
|
||||
{
|
||||
}
|
||||
|
||||
void MemcpyCommand::Execute(DrawerThread *thread)
|
||||
{
|
||||
int start = thread->skipped_by_thread(0);
|
||||
int count = thread->count_for_thread(0, height);
|
||||
int sstep = thread->num_cores * srcpitch * pixelsize;
|
||||
int dstep = thread->num_cores * width * pixelsize;
|
||||
int size = width * pixelsize;
|
||||
uint8_t *d = (uint8_t*)dest + start * width * pixelsize;
|
||||
const uint8_t *s = (const uint8_t*)src + start * srcpitch * pixelsize;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
memcpy(d, s, size);
|
||||
d += dstep;
|
||||
s += sstep;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,6 +109,22 @@ private:
|
|||
size_t count = 0;
|
||||
};
|
||||
|
||||
// Copy finished rows to video memory
|
||||
class MemcpyCommand : public DrawerCommand
|
||||
{
|
||||
public:
|
||||
MemcpyCommand(void *dest, const void *src, int width, int height, int srcpitch, int pixelsize);
|
||||
void Execute(DrawerThread *thread);
|
||||
|
||||
private:
|
||||
void *dest;
|
||||
const void *src;
|
||||
int width;
|
||||
int height;
|
||||
int srcpitch;
|
||||
int pixelsize;
|
||||
};
|
||||
|
||||
class DrawerCommandQueue;
|
||||
typedef std::shared_ptr<DrawerCommandQueue> DrawerCommandQueuePtr;
|
||||
|
||||
|
|
|
@ -157,13 +157,13 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &
|
|||
}
|
||||
}
|
||||
|
||||
void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target)
|
||||
void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target, void *videobuffer)
|
||||
{
|
||||
if (V_IsPolyRenderer())
|
||||
{
|
||||
PolyRenderer::Instance()->Viewpoint = r_viewpoint;
|
||||
PolyRenderer::Instance()->Viewwindow = r_viewwindow;
|
||||
PolyRenderer::Instance()->RenderView(player, target);
|
||||
PolyRenderer::Instance()->RenderView(player, target, videobuffer);
|
||||
r_viewpoint = PolyRenderer::Instance()->Viewpoint;
|
||||
r_viewwindow = PolyRenderer::Instance()->Viewwindow;
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target)
|
|||
{
|
||||
mScene.MainThread()->Viewport->viewpoint = r_viewpoint;
|
||||
mScene.MainThread()->Viewport->viewwindow = r_viewwindow;
|
||||
mScene.RenderView(player, target);
|
||||
mScene.RenderView(player, target, videobuffer);
|
||||
r_viewpoint = mScene.MainThread()->Viewport->viewpoint;
|
||||
r_viewwindow = mScene.MainThread()->Viewport->viewwindow;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ struct FSoftwareRenderer : public FRenderer
|
|||
void Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitlist) override;
|
||||
|
||||
// render 3D view
|
||||
void RenderView(player_t *player, DCanvas *target) override;
|
||||
void RenderView(player_t *player, DCanvas *target, void *videobuffer) override;
|
||||
|
||||
// renders view to a savegame picture
|
||||
void WriteSavePic (player_t *player, FileWriter *file, int width, int height) override;
|
||||
|
|
|
@ -99,7 +99,6 @@ sector_t *SWSceneDrawer::RenderView(player_t *player)
|
|||
FBTextureIndex = (FBTextureIndex + 1) % 2;
|
||||
auto &fbtex = FBTexture[FBTextureIndex];
|
||||
|
||||
DCanvas buffer(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor());
|
||||
if (fbtex == nullptr || fbtex->SystemTexture[0] == nullptr ||
|
||||
fbtex->GetWidth() != screen->GetWidth() ||
|
||||
fbtex->GetHeight() != screen->GetHeight() ||
|
||||
|
@ -111,12 +110,14 @@ sector_t *SWSceneDrawer::RenderView(player_t *player)
|
|||
fbtex->SystemTexture[0]->AllocateBuffer(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor() ? 4 : 1);
|
||||
auto mat = FMaterial::ValidateTexture(fbtex.get(), false);
|
||||
mat->AddTextureLayer(PaletteTexture.get());
|
||||
|
||||
Canvas.reset();
|
||||
Canvas.reset(new DSimpleCanvas(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor()));
|
||||
}
|
||||
|
||||
auto buf = fbtex->SystemTexture[0]->MapBuffer();
|
||||
if (!buf) I_FatalError("Unable to map buffer for software rendering");
|
||||
buffer.SetBuffer(screen->GetWidth(), screen->GetHeight(), screen->GetWidth(), buf);
|
||||
SWRenderer->RenderView(player, &buffer);
|
||||
SWRenderer->RenderView(player, Canvas.get(), buf);
|
||||
fbtex->SystemTexture[0]->CreateTexture(nullptr, screen->GetWidth(), screen->GetHeight(), 0, false, 0, "swbuffer");
|
||||
|
||||
auto map = swrenderer::CameraLight::Instance()->ShaderColormap();
|
||||
|
|
|
@ -16,6 +16,7 @@ class SWSceneDrawer
|
|||
std::unique_ptr<FSWSceneTexture> FBTexture[2];
|
||||
int FBTextureIndex = 0;
|
||||
bool FBIsTruecolor = false;
|
||||
std::unique_ptr<DSimpleCanvas> Canvas;
|
||||
|
||||
public:
|
||||
SWSceneDrawer();
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace swrenderer
|
|||
clearcolor = color;
|
||||
}
|
||||
|
||||
void RenderScene::RenderView(player_t *player, DCanvas *target)
|
||||
void RenderScene::RenderView(player_t *player, DCanvas *target, void *videobuffer)
|
||||
{
|
||||
auto viewport = MainThread()->Viewport.get();
|
||||
viewport->RenderTarget = target;
|
||||
|
@ -131,6 +131,10 @@ namespace swrenderer
|
|||
|
||||
RenderActorView(player->mo);
|
||||
|
||||
auto copyqueue = std::make_shared<DrawerCommandQueue>(MainThread()->FrameMemory.get());
|
||||
copyqueue->Push<MemcpyCommand>(videobuffer, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1);
|
||||
DrawerThreads::Execute(copyqueue);
|
||||
|
||||
DrawerWaitCycles.Clock();
|
||||
DrawerThreads::WaitForWorkers();
|
||||
DrawerWaitCycles.Unclock();
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace swrenderer
|
|||
|
||||
void SetClearColor(int color);
|
||||
|
||||
void RenderView(player_t *player, DCanvas *target);
|
||||
void RenderView(player_t *player, DCanvas *target, void *videobuffer);
|
||||
void RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines = false);
|
||||
|
||||
bool DontMapLines() const { return dontmaplines; }
|
||||
|
|
Loading…
Reference in a new issue