mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-10 23:01:59 +00:00
- fixed output of software renderers with Vulkan backend
Vulkan hardware buffer for software canvas may have some padding Software renderers should be aware of buffer's pitch in order to copy pixels properly https://forum.zdoom.org/viewtopic.php?t=64562
This commit is contained in:
parent
edcce76f3a
commit
56557a17f1
14 changed files with 41 additions and 27 deletions
|
@ -24,7 +24,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, void *videobuffer) = 0;
|
virtual void RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch) = 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;
|
||||||
|
|
|
@ -191,6 +191,7 @@ void FHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
|
||||||
int rh = GetTexDimension(h);
|
int rh = GetTexDimension(h);
|
||||||
if (texelsize < 1 || texelsize > 4) texelsize = 4;
|
if (texelsize < 1 || texelsize > 4) texelsize = 4;
|
||||||
glTextureBytes = texelsize;
|
glTextureBytes = texelsize;
|
||||||
|
bufferpitch = w;
|
||||||
if (rw == w || rh == h)
|
if (rw == w || rh == h)
|
||||||
{
|
{
|
||||||
glGenBuffers(1, &glBufferID);
|
glGenBuffers(1, &glBufferID);
|
||||||
|
|
|
@ -14,10 +14,6 @@ public:
|
||||||
MAX_TEXTURES = 16
|
MAX_TEXTURES = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
IHardwareTexture() {}
|
IHardwareTexture() {}
|
||||||
virtual ~IHardwareTexture() {}
|
virtual ~IHardwareTexture() {}
|
||||||
|
|
||||||
|
@ -26,5 +22,9 @@ public:
|
||||||
virtual unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name) = 0;
|
virtual unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name) = 0;
|
||||||
|
|
||||||
void Resize(int swidth, int sheight, int width, int height, unsigned char *src_data, unsigned char *dst_data);
|
void Resize(int swidth, int sheight, int width, int height, unsigned char *src_data, unsigned char *dst_data);
|
||||||
};
|
|
||||||
|
|
||||||
|
int GetBufferPitch() const { return bufferpitch; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int bufferpitch = -1;
|
||||||
|
};
|
||||||
|
|
|
@ -59,7 +59,7 @@ PolyRenderer::PolyRenderer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolyRenderer::RenderView(player_t *player, DCanvas *target, void *videobuffer)
|
void PolyRenderer::RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch)
|
||||||
{
|
{
|
||||||
using namespace swrenderer;
|
using namespace swrenderer;
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ void PolyRenderer::RenderView(player_t *player, DCanvas *target, void *videobuff
|
||||||
Threads.MainThread()->FlushDrawQueue();
|
Threads.MainThread()->FlushDrawQueue();
|
||||||
|
|
||||||
auto copyqueue = std::make_shared<DrawerCommandQueue>(Threads.MainThread()->FrameMemory.get());
|
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);
|
copyqueue->Push<MemcpyCommand>(videobuffer, bufferpitch, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1);
|
||||||
DrawerThreads::Execute(copyqueue);
|
DrawerThreads::Execute(copyqueue);
|
||||||
|
|
||||||
PolyDrawerWaitCycles.Clock();
|
PolyDrawerWaitCycles.Clock();
|
||||||
|
|
|
@ -49,7 +49,7 @@ class PolyRenderer
|
||||||
public:
|
public:
|
||||||
PolyRenderer();
|
PolyRenderer();
|
||||||
|
|
||||||
void RenderView(player_t *player, DCanvas *target, void *videobuffer);
|
void RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch);
|
||||||
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();
|
||||||
|
|
||||||
|
|
|
@ -271,8 +271,8 @@ void GroupMemoryBarrierCommand::Execute(DrawerThread *thread)
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
MemcpyCommand::MemcpyCommand(void *dest, const void *src, int width, int height, int srcpitch, int pixelsize)
|
MemcpyCommand::MemcpyCommand(void *dest, int destpitch, const void *src, int width, int height, int srcpitch, int pixelsize)
|
||||||
: dest(dest), src(src), width(width), height(height), srcpitch(srcpitch), pixelsize(pixelsize)
|
: dest(dest), src(src), destpitch(destpitch), width(width), height(height), srcpitch(srcpitch), pixelsize(pixelsize)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,9 +281,9 @@ void MemcpyCommand::Execute(DrawerThread *thread)
|
||||||
int start = thread->skipped_by_thread(0);
|
int start = thread->skipped_by_thread(0);
|
||||||
int count = thread->count_for_thread(0, height);
|
int count = thread->count_for_thread(0, height);
|
||||||
int sstep = thread->num_cores * srcpitch * pixelsize;
|
int sstep = thread->num_cores * srcpitch * pixelsize;
|
||||||
int dstep = thread->num_cores * width * pixelsize;
|
int dstep = thread->num_cores * destpitch * pixelsize;
|
||||||
int size = width * pixelsize;
|
int size = width * pixelsize;
|
||||||
uint8_t *d = (uint8_t*)dest + start * width * pixelsize;
|
uint8_t *d = (uint8_t*)dest + start * destpitch * pixelsize;
|
||||||
const uint8_t *s = (const uint8_t*)src + start * srcpitch * pixelsize;
|
const uint8_t *s = (const uint8_t*)src + start * srcpitch * pixelsize;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -125,12 +125,13 @@ private:
|
||||||
class MemcpyCommand : public DrawerCommand
|
class MemcpyCommand : public DrawerCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MemcpyCommand(void *dest, const void *src, int width, int height, int srcpitch, int pixelsize);
|
MemcpyCommand(void *dest, int destpitch, const void *src, int width, int height, int srcpitch, int pixelsize);
|
||||||
void Execute(DrawerThread *thread);
|
void Execute(DrawerThread *thread);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void *dest;
|
void *dest;
|
||||||
const void *src;
|
const void *src;
|
||||||
|
int destpitch;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
int srcpitch;
|
int srcpitch;
|
||||||
|
|
|
@ -183,13 +183,13 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &
|
||||||
FImageSource::EndPrecaching();
|
FImageSource::EndPrecaching();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target, void *videobuffer)
|
void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch)
|
||||||
{
|
{
|
||||||
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, videobuffer);
|
PolyRenderer::Instance()->RenderView(player, target, videobuffer, bufferpitch);
|
||||||
r_viewpoint = PolyRenderer::Instance()->Viewpoint;
|
r_viewpoint = PolyRenderer::Instance()->Viewpoint;
|
||||||
r_viewwindow = PolyRenderer::Instance()->Viewwindow;
|
r_viewwindow = PolyRenderer::Instance()->Viewwindow;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target, void *vide
|
||||||
{
|
{
|
||||||
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, videobuffer);
|
mScene.RenderView(player, target, videobuffer, bufferpitch);
|
||||||
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, void *videobuffer) override;
|
void RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch) 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;
|
||||||
|
|
|
@ -106,10 +106,11 @@ sector_t *SWSceneDrawer::RenderView(player_t *player)
|
||||||
Canvas.reset(new DCanvas(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor()));
|
Canvas.reset(new DCanvas(screen->GetWidth(), screen->GetHeight(), V_IsTrueColor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto buf = fbtex->GetSystemTexture()->MapBuffer();
|
IHardwareTexture *systemTexture = fbtex->GetSystemTexture();
|
||||||
|
auto buf = systemTexture->MapBuffer();
|
||||||
if (!buf) I_FatalError("Unable to map buffer for software rendering");
|
if (!buf) I_FatalError("Unable to map buffer for software rendering");
|
||||||
SWRenderer->RenderView(player, Canvas.get(), buf);
|
SWRenderer->RenderView(player, Canvas.get(), buf, systemTexture->GetBufferPitch());
|
||||||
fbtex->GetSystemTexture()->CreateTexture(nullptr, screen->GetWidth(), screen->GetHeight(), 0, false, 0, "swbuffer");
|
systemTexture->CreateTexture(nullptr, screen->GetWidth(), screen->GetHeight(), 0, false, 0, "swbuffer");
|
||||||
|
|
||||||
auto map = swrenderer::CameraLight::Instance()->ShaderColormap();
|
auto map = swrenderer::CameraLight::Instance()->ShaderColormap();
|
||||||
screen->DrawTexture(fbtex.get(), 0, 0, DTA_SpecialColormap, map, TAG_DONE);
|
screen->DrawTexture(fbtex.get(), 0, 0, DTA_SpecialColormap, map, TAG_DONE);
|
||||||
|
|
|
@ -90,7 +90,7 @@ namespace swrenderer
|
||||||
clearcolor = color;
|
clearcolor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderScene::RenderView(player_t *player, DCanvas *target, void *videobuffer)
|
void RenderScene::RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch)
|
||||||
{
|
{
|
||||||
auto viewport = MainThread()->Viewport.get();
|
auto viewport = MainThread()->Viewport.get();
|
||||||
viewport->RenderTarget = target;
|
viewport->RenderTarget = target;
|
||||||
|
@ -132,7 +132,7 @@ namespace swrenderer
|
||||||
RenderActorView(player->mo, true, false);
|
RenderActorView(player->mo, true, false);
|
||||||
|
|
||||||
auto copyqueue = std::make_shared<DrawerCommandQueue>(MainThread()->FrameMemory.get());
|
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);
|
copyqueue->Push<MemcpyCommand>(videobuffer, bufferpitch, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1);
|
||||||
DrawerThreads::Execute(copyqueue);
|
DrawerThreads::Execute(copyqueue);
|
||||||
|
|
||||||
DrawerWaitCycles.Clock();
|
DrawerWaitCycles.Clock();
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace swrenderer
|
||||||
|
|
||||||
void SetClearColor(int color);
|
void SetClearColor(int color);
|
||||||
|
|
||||||
void RenderView(player_t *player, DCanvas *target, void *videobuffer);
|
void RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch);
|
||||||
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; }
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
|
|
||||||
bool isFormatSupported(VulkanDevice *device);
|
bool isFormatSupported(VulkanDevice *device);
|
||||||
|
|
||||||
std::unique_ptr<VulkanImage> create(VulkanDevice *device);
|
std::unique_ptr<VulkanImage> create(VulkanDevice *device, VkDeviceSize* allocatedBytes = nullptr);
|
||||||
std::unique_ptr<VulkanImage> tryCreate(VulkanDevice *device);
|
std::unique_ptr<VulkanImage> tryCreate(VulkanDevice *device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -424,7 +424,7 @@ inline bool ImageBuilder::isFormatSupported(VulkanDevice *device)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::unique_ptr<VulkanImage> ImageBuilder::create(VulkanDevice *device)
|
inline std::unique_ptr<VulkanImage> ImageBuilder::create(VulkanDevice *device, VkDeviceSize* allocatedBytes)
|
||||||
{
|
{
|
||||||
VkImage image;
|
VkImage image;
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
|
@ -433,6 +433,14 @@ inline std::unique_ptr<VulkanImage> ImageBuilder::create(VulkanDevice *device)
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
I_FatalError("Could not create vulkan image");
|
I_FatalError("Could not create vulkan image");
|
||||||
|
|
||||||
|
if (allocatedBytes != nullptr)
|
||||||
|
{
|
||||||
|
VmaAllocationInfo allocatedInfo;
|
||||||
|
vmaGetAllocationInfo(device->allocator, allocation, &allocatedInfo);
|
||||||
|
|
||||||
|
*allocatedBytes = allocatedInfo.size;
|
||||||
|
}
|
||||||
|
|
||||||
return std::make_unique<VulkanImage>(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels);
|
return std::make_unique<VulkanImage>(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -368,6 +368,7 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
|
||||||
VkFormat format = texelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM;
|
VkFormat format = texelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM;
|
||||||
|
|
||||||
ImageBuilder imgbuilder;
|
ImageBuilder imgbuilder;
|
||||||
|
VkDeviceSize allocatedBytes = 0;
|
||||||
imgbuilder.setFormat(format);
|
imgbuilder.setFormat(format);
|
||||||
imgbuilder.setSize(w, h);
|
imgbuilder.setSize(w, h);
|
||||||
imgbuilder.setLinearTiling();
|
imgbuilder.setLinearTiling();
|
||||||
|
@ -375,7 +376,7 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
|
||||||
imgbuilder.setMemoryType(
|
imgbuilder.setMemoryType(
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
mImage = imgbuilder.create(fb->device);
|
mImage = imgbuilder.create(fb->device, &allocatedBytes);
|
||||||
mImage->SetDebugName("VkHardwareTexture.mImage");
|
mImage->SetDebugName("VkHardwareTexture.mImage");
|
||||||
mImageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
mImageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
mTexelsize = texelsize;
|
mTexelsize = texelsize;
|
||||||
|
@ -390,6 +391,8 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
|
||||||
PipelineBarrier imageTransition;
|
PipelineBarrier imageTransition;
|
||||||
imageTransition.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, mImageLayout, 0, VK_ACCESS_SHADER_READ_BIT);
|
imageTransition.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, mImageLayout, 0, VK_ACCESS_SHADER_READ_BIT);
|
||||||
imageTransition.execute(cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
imageTransition.execute(cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
|
|
||||||
|
bufferpitch = int(allocatedBytes / h / texelsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue