- 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:
Magnus Norddahl 2018-07-20 05:48:15 +02:00
parent 4d35b12808
commit a841602d70
15 changed files with 70 additions and 28 deletions

View file

@ -296,9 +296,6 @@ void FHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
{ {
glGenBuffers(1, &glBufferID); glGenBuffers(1, &glBufferID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 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); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
} }
@ -308,16 +305,7 @@ void FHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
uint8_t *FHardwareTexture::MapBuffer() uint8_t *FHardwareTexture::MapBuffer()
{ {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBufferID); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBufferID);
if (screen->hwcaps & RFL_BUFFER_STORAGE) return (uint8_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
{
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);
}
} }
//=========================================================================== //===========================================================================

View file

@ -169,6 +169,7 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs, const vo
args.uniforms = &drawargs; args.uniforms = &drawargs;
args.destBgra = dest_bgra; args.destBgra = dest_bgra;
args.stencilbuffer = PolyStencilBuffer::Instance()->Values(); args.stencilbuffer = PolyStencilBuffer::Instance()->Values();
args.stencilpitch = PolyStencilBuffer::Instance()->Width();
args.zbuffer = PolyZBuffer::Instance()->Values(); args.zbuffer = PolyZBuffer::Instance()->Values();
args.depthOffset = weaponScene ? 1.0f : 0.0f; args.depthOffset = weaponScene ? 1.0f : 0.0f;
@ -222,6 +223,7 @@ void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void
args.uniforms = &drawargs; args.uniforms = &drawargs;
args.destBgra = dest_bgra; args.destBgra = dest_bgra;
args.stencilbuffer = PolyStencilBuffer::Instance()->Values(); args.stencilbuffer = PolyStencilBuffer::Instance()->Values();
args.stencilpitch = PolyStencilBuffer::Instance()->Width();
args.zbuffer = PolyZBuffer::Instance()->Values(); args.zbuffer = PolyZBuffer::Instance()->Values();
args.depthOffset = weaponScene ? 1.0f : 0.0f; args.depthOffset = weaponScene ? 1.0f : 0.0f;

View file

@ -153,8 +153,8 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat
int x = leftEdge[y]; int x = leftEdge[y];
int xend = rightEdge[y]; int xend = rightEdge[y];
float *zbufferLine = args->zbuffer + args->pitch * y; float *zbufferLine = args->zbuffer + args->stencilpitch * y;
uint8_t *stencilLine = args->stencilbuffer + args->pitch * y; uint8_t *stencilLine = args->stencilbuffer + args->stencilpitch * y;
float startX = x + (0.5f - v1X); float startX = x + (0.5f - v1X);
float startY = y + (0.5f - v1Y); float startY = y + (0.5f - v1Y);

View file

@ -53,6 +53,7 @@ struct TriDrawTriangleArgs
int32_t clipright; int32_t clipright;
int32_t clipbottom; int32_t clipbottom;
uint8_t *stencilbuffer; uint8_t *stencilbuffer;
int stencilpitch;
float *zbuffer; float *zbuffer;
const PolyDrawArgs *uniforms; const PolyDrawArgs *uniforms;
bool destBgra; bool destBgra;

View file

@ -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; using namespace swrenderer;
@ -70,6 +70,11 @@ void PolyRenderer::RenderView(player_t *player, DCanvas *target)
RenderActorView(player->mo, false); RenderActorView(player->mo, false);
Threads.MainThread()->FlushDrawQueue(); 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(); PolyDrawerWaitCycles.Clock();
DrawerThreads::WaitForWorkers(); DrawerThreads::WaitForWorkers();
PolyDrawerWaitCycles.Unclock(); PolyDrawerWaitCycles.Unclock();

View file

@ -49,7 +49,7 @@ class PolyRenderer
public: public:
PolyRenderer(); 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 RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines);
void RenderRemainingPlayerSprites(); void RenderRemainingPlayerSprites();

View file

@ -23,7 +23,7 @@ struct FRenderer
virtual void Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitlist) = 0; virtual void Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitlist) = 0;
// render 3D view // 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 // renders view to a savegame picture
virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height) = 0; virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height) = 0;

View file

@ -223,3 +223,27 @@ void GroupMemoryBarrierCommand::Execute(DrawerThread *thread)
condition.notify_all(); condition.notify_all();
condition.wait(lock, [&]() { return count >= (size_t)thread->num_cores; }); 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;
}
}

View file

@ -109,6 +109,22 @@ private:
size_t count = 0; 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; class DrawerCommandQueue;
typedef std::shared_ptr<DrawerCommandQueue> DrawerCommandQueuePtr; typedef std::shared_ptr<DrawerCommandQueue> DrawerCommandQueuePtr;

View file

@ -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()) if (V_IsPolyRenderer())
{ {
PolyRenderer::Instance()->Viewpoint = r_viewpoint; PolyRenderer::Instance()->Viewpoint = r_viewpoint;
PolyRenderer::Instance()->Viewwindow = r_viewwindow; PolyRenderer::Instance()->Viewwindow = r_viewwindow;
PolyRenderer::Instance()->RenderView(player, target); PolyRenderer::Instance()->RenderView(player, target, videobuffer);
r_viewpoint = PolyRenderer::Instance()->Viewpoint; r_viewpoint = PolyRenderer::Instance()->Viewpoint;
r_viewwindow = PolyRenderer::Instance()->Viewwindow; 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->viewpoint = r_viewpoint;
mScene.MainThread()->Viewport->viewwindow = r_viewwindow; mScene.MainThread()->Viewport->viewwindow = r_viewwindow;
mScene.RenderView(player, target); mScene.RenderView(player, target, videobuffer);
r_viewpoint = mScene.MainThread()->Viewport->viewpoint; r_viewpoint = mScene.MainThread()->Viewport->viewpoint;
r_viewwindow = mScene.MainThread()->Viewport->viewwindow; r_viewwindow = mScene.MainThread()->Viewport->viewwindow;
} }

View file

@ -12,7 +12,7 @@ struct FSoftwareRenderer : public FRenderer
void Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitlist) override; void Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &actorhitlist) override;
// render 3D view // 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 // renders view to a savegame picture
void WriteSavePic (player_t *player, FileWriter *file, int width, int height) override; void WriteSavePic (player_t *player, FileWriter *file, int width, int height) override;

View file

@ -99,7 +99,6 @@ sector_t *SWSceneDrawer::RenderView(player_t *player)
FBTextureIndex = (FBTextureIndex + 1) % 2; FBTextureIndex = (FBTextureIndex + 1) % 2;
auto &fbtex = FBTexture[FBTextureIndex]; auto &fbtex = FBTexture[FBTextureIndex];
DCanvas buffer(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor());
if (fbtex == nullptr || fbtex->SystemTexture[0] == nullptr || if (fbtex == nullptr || fbtex->SystemTexture[0] == nullptr ||
fbtex->GetWidth() != screen->GetWidth() || fbtex->GetWidth() != screen->GetWidth() ||
fbtex->GetHeight() != screen->GetHeight() || 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); fbtex->SystemTexture[0]->AllocateBuffer(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor() ? 4 : 1);
auto mat = FMaterial::ValidateTexture(fbtex.get(), false); auto mat = FMaterial::ValidateTexture(fbtex.get(), false);
mat->AddTextureLayer(PaletteTexture.get()); mat->AddTextureLayer(PaletteTexture.get());
Canvas.reset();
Canvas.reset(new DSimpleCanvas(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor()));
} }
auto buf = fbtex->SystemTexture[0]->MapBuffer(); auto buf = fbtex->SystemTexture[0]->MapBuffer();
if (!buf) I_FatalError("Unable to map buffer for software rendering"); if (!buf) I_FatalError("Unable to map buffer for software rendering");
buffer.SetBuffer(screen->GetWidth(), screen->GetHeight(), screen->GetWidth(), buf); SWRenderer->RenderView(player, Canvas.get(), buf);
SWRenderer->RenderView(player, &buffer);
fbtex->SystemTexture[0]->CreateTexture(nullptr, screen->GetWidth(), screen->GetHeight(), 0, false, 0, "swbuffer"); fbtex->SystemTexture[0]->CreateTexture(nullptr, screen->GetWidth(), screen->GetHeight(), 0, false, 0, "swbuffer");
auto map = swrenderer::CameraLight::Instance()->ShaderColormap(); auto map = swrenderer::CameraLight::Instance()->ShaderColormap();

View file

@ -16,6 +16,7 @@ class SWSceneDrawer
std::unique_ptr<FSWSceneTexture> FBTexture[2]; std::unique_ptr<FSWSceneTexture> FBTexture[2];
int FBTextureIndex = 0; int FBTextureIndex = 0;
bool FBIsTruecolor = false; bool FBIsTruecolor = false;
std::unique_ptr<DSimpleCanvas> Canvas;
public: public:
SWSceneDrawer(); SWSceneDrawer();

View file

@ -90,7 +90,7 @@ namespace swrenderer
clearcolor = color; 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(); auto viewport = MainThread()->Viewport.get();
viewport->RenderTarget = target; viewport->RenderTarget = target;
@ -131,6 +131,10 @@ namespace swrenderer
RenderActorView(player->mo); 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(); DrawerWaitCycles.Clock();
DrawerThreads::WaitForWorkers(); DrawerThreads::WaitForWorkers();
DrawerWaitCycles.Unclock(); DrawerWaitCycles.Unclock();

View file

@ -48,7 +48,7 @@ namespace swrenderer
void SetClearColor(int color); 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); void RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines = false);
bool DontMapLines() const { return dontmaplines; } bool DontMapLines() const { return dontmaplines; }