mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-14 08:31:23 +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,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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
Loading…
Reference in a new issue