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;
|
||||
|
||||
// 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
|
||||
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);
|
||||
if (texelsize < 1 || texelsize > 4) texelsize = 4;
|
||||
glTextureBytes = texelsize;
|
||||
bufferpitch = w;
|
||||
if (rw == w || rh == h)
|
||||
{
|
||||
glGenBuffers(1, &glBufferID);
|
||||
|
|
|
@ -14,10 +14,6 @@ public:
|
|||
MAX_TEXTURES = 16
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
|
||||
public:
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -73,7 +73,7 @@ void PolyRenderer::RenderView(player_t *player, DCanvas *target, void *videobuff
|
|||
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);
|
||||
copyqueue->Push<MemcpyCommand>(videobuffer, bufferpitch, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1);
|
||||
DrawerThreads::Execute(copyqueue);
|
||||
|
||||
PolyDrawerWaitCycles.Clock();
|
||||
|
|
|
@ -49,7 +49,7 @@ class PolyRenderer
|
|||
public:
|
||||
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 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)
|
||||
: dest(dest), src(src), width(width), height(height), srcpitch(srcpitch), pixelsize(pixelsize)
|
||||
MemcpyCommand::MemcpyCommand(void *dest, int destpitch, const void *src, int width, int height, int srcpitch, int 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 count = thread->count_for_thread(0, height);
|
||||
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;
|
||||
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;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
|
|
|
@ -125,12 +125,13 @@ private:
|
|||
class MemcpyCommand : public DrawerCommand
|
||||
{
|
||||
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);
|
||||
|
||||
private:
|
||||
void *dest;
|
||||
const void *src;
|
||||
int destpitch;
|
||||
int width;
|
||||
int height;
|
||||
int srcpitch;
|
||||
|
|
|
@ -183,13 +183,13 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &
|
|||
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())
|
||||
{
|
||||
PolyRenderer::Instance()->Viewpoint = r_viewpoint;
|
||||
PolyRenderer::Instance()->Viewwindow = r_viewwindow;
|
||||
PolyRenderer::Instance()->RenderView(player, target, videobuffer);
|
||||
PolyRenderer::Instance()->RenderView(player, target, videobuffer, bufferpitch);
|
||||
r_viewpoint = PolyRenderer::Instance()->Viewpoint;
|
||||
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->viewwindow = r_viewwindow;
|
||||
mScene.RenderView(player, target, videobuffer);
|
||||
mScene.RenderView(player, target, videobuffer, bufferpitch);
|
||||
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, void *videobuffer) override;
|
||||
void RenderView(player_t *player, DCanvas *target, void *videobuffer, int bufferpitch) override;
|
||||
|
||||
// renders view to a savegame picture
|
||||
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()));
|
||||
}
|
||||
|
||||
auto buf = fbtex->GetSystemTexture()->MapBuffer();
|
||||
IHardwareTexture *systemTexture = fbtex->GetSystemTexture();
|
||||
auto buf = systemTexture->MapBuffer();
|
||||
if (!buf) I_FatalError("Unable to map buffer for software rendering");
|
||||
SWRenderer->RenderView(player, Canvas.get(), buf);
|
||||
fbtex->GetSystemTexture()->CreateTexture(nullptr, screen->GetWidth(), screen->GetHeight(), 0, false, 0, "swbuffer");
|
||||
SWRenderer->RenderView(player, Canvas.get(), buf, systemTexture->GetBufferPitch());
|
||||
systemTexture->CreateTexture(nullptr, screen->GetWidth(), screen->GetHeight(), 0, false, 0, "swbuffer");
|
||||
|
||||
auto map = swrenderer::CameraLight::Instance()->ShaderColormap();
|
||||
screen->DrawTexture(fbtex.get(), 0, 0, DTA_SpecialColormap, map, TAG_DONE);
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace swrenderer
|
|||
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();
|
||||
viewport->RenderTarget = target;
|
||||
|
@ -132,7 +132,7 @@ namespace swrenderer
|
|||
RenderActorView(player->mo, true, false);
|
||||
|
||||
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);
|
||||
|
||||
DrawerWaitCycles.Clock();
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace swrenderer
|
|||
|
||||
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);
|
||||
|
||||
bool DontMapLines() const { return dontmaplines; }
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
|
||||
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);
|
||||
|
||||
private:
|
||||
|
@ -424,7 +424,7 @@ inline bool ImageBuilder::isFormatSupported(VulkanDevice *device)
|
|||
return true;
|
||||
}
|
||||
|
||||
inline std::unique_ptr<VulkanImage> ImageBuilder::create(VulkanDevice *device)
|
||||
inline std::unique_ptr<VulkanImage> ImageBuilder::create(VulkanDevice *device, VkDeviceSize* allocatedBytes)
|
||||
{
|
||||
VkImage image;
|
||||
VmaAllocation allocation;
|
||||
|
@ -433,6 +433,14 @@ inline std::unique_ptr<VulkanImage> ImageBuilder::create(VulkanDevice *device)
|
|||
if (result != VK_SUCCESS)
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
ImageBuilder imgbuilder;
|
||||
VkDeviceSize allocatedBytes = 0;
|
||||
imgbuilder.setFormat(format);
|
||||
imgbuilder.setSize(w, h);
|
||||
imgbuilder.setLinearTiling();
|
||||
|
@ -375,7 +376,7 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
|
|||
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_DEVICE_LOCAL_BIT);
|
||||
mImage = imgbuilder.create(fb->device);
|
||||
mImage = imgbuilder.create(fb->device, &allocatedBytes);
|
||||
mImage->SetDebugName("VkHardwareTexture.mImage");
|
||||
mImageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
mTexelsize = texelsize;
|
||||
|
@ -390,6 +391,8 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
|
|||
PipelineBarrier imageTransition;
|
||||
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);
|
||||
|
||||
bufferpitch = int(allocatedBytes / h / texelsize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue