diff --git a/src/r_renderer.h b/src/r_renderer.h index 126d7a2ee..1f3dec145 100644 --- a/src/r_renderer.h +++ b/src/r_renderer.h @@ -24,7 +24,7 @@ struct FRenderer virtual void Precache(uint8_t *texhitlist, TMap &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; diff --git a/src/rendering/gl/textures/gl_hwtexture.cpp b/src/rendering/gl/textures/gl_hwtexture.cpp index e4736f4d6..01d818f5b 100644 --- a/src/rendering/gl/textures/gl_hwtexture.cpp +++ b/src/rendering/gl/textures/gl_hwtexture.cpp @@ -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); diff --git a/src/rendering/hwrenderer/textures/hw_ihwtexture.h b/src/rendering/hwrenderer/textures/hw_ihwtexture.h index f05baf47d..7000edccb 100644 --- a/src/rendering/hwrenderer/textures/hw_ihwtexture.h +++ b/src/rendering/hwrenderer/textures/hw_ihwtexture.h @@ -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; +}; diff --git a/src/rendering/polyrenderer/poly_renderer.cpp b/src/rendering/polyrenderer/poly_renderer.cpp index 491f1b8ee..9c3642488 100644 --- a/src/rendering/polyrenderer/poly_renderer.cpp +++ b/src/rendering/polyrenderer/poly_renderer.cpp @@ -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(Threads.MainThread()->FrameMemory.get()); - copyqueue->Push(videobuffer, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1); + copyqueue->Push(videobuffer, bufferpitch, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1); DrawerThreads::Execute(copyqueue); PolyDrawerWaitCycles.Clock(); diff --git a/src/rendering/polyrenderer/poly_renderer.h b/src/rendering/polyrenderer/poly_renderer.h index 4750d2b04..b40f5d44d 100644 --- a/src/rendering/polyrenderer/poly_renderer.h +++ b/src/rendering/polyrenderer/poly_renderer.h @@ -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(); diff --git a/src/rendering/swrenderer/drawers/r_thread.cpp b/src/rendering/swrenderer/drawers/r_thread.cpp index e8b6eeada..b04bde383 100644 --- a/src/rendering/swrenderer/drawers/r_thread.cpp +++ b/src/rendering/swrenderer/drawers/r_thread.cpp @@ -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++) { diff --git a/src/rendering/swrenderer/drawers/r_thread.h b/src/rendering/swrenderer/drawers/r_thread.h index f12193a49..eb804ac76 100644 --- a/src/rendering/swrenderer/drawers/r_thread.h +++ b/src/rendering/swrenderer/drawers/r_thread.h @@ -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; diff --git a/src/rendering/swrenderer/r_swrenderer.cpp b/src/rendering/swrenderer/r_swrenderer.cpp index cf153551f..c2536e3d2 100644 --- a/src/rendering/swrenderer/r_swrenderer.cpp +++ b/src/rendering/swrenderer/r_swrenderer.cpp @@ -183,13 +183,13 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap & 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; } diff --git a/src/rendering/swrenderer/r_swrenderer.h b/src/rendering/swrenderer/r_swrenderer.h index 84627f2cd..f2cdb116d 100644 --- a/src/rendering/swrenderer/r_swrenderer.h +++ b/src/rendering/swrenderer/r_swrenderer.h @@ -12,7 +12,7 @@ struct FSoftwareRenderer : public FRenderer void Precache(uint8_t *texhitlist, TMap &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; diff --git a/src/rendering/swrenderer/r_swscene.cpp b/src/rendering/swrenderer/r_swscene.cpp index 164ffd536..8c24a3db1 100644 --- a/src/rendering/swrenderer/r_swscene.cpp +++ b/src/rendering/swrenderer/r_swscene.cpp @@ -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); diff --git a/src/rendering/swrenderer/scene/r_scene.cpp b/src/rendering/swrenderer/scene/r_scene.cpp index b598f49b0..32a1a47c9 100644 --- a/src/rendering/swrenderer/scene/r_scene.cpp +++ b/src/rendering/swrenderer/scene/r_scene.cpp @@ -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(MainThread()->FrameMemory.get()); - copyqueue->Push(videobuffer, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1); + copyqueue->Push(videobuffer, bufferpitch, target->GetPixels(), target->GetWidth(), target->GetHeight(), target->GetPitch(), target->IsBgra() ? 4 : 1); DrawerThreads::Execute(copyqueue); DrawerWaitCycles.Clock(); diff --git a/src/rendering/swrenderer/scene/r_scene.h b/src/rendering/swrenderer/scene/r_scene.h index cba258056..035d12133 100644 --- a/src/rendering/swrenderer/scene/r_scene.h +++ b/src/rendering/swrenderer/scene/r_scene.h @@ -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; } diff --git a/src/rendering/vulkan/system/vk_builders.h b/src/rendering/vulkan/system/vk_builders.h index af5b54c82..2b959aa61 100644 --- a/src/rendering/vulkan/system/vk_builders.h +++ b/src/rendering/vulkan/system/vk_builders.h @@ -47,7 +47,7 @@ public: bool isFormatSupported(VulkanDevice *device); - std::unique_ptr create(VulkanDevice *device); + std::unique_ptr create(VulkanDevice *device, VkDeviceSize* allocatedBytes = nullptr); std::unique_ptr tryCreate(VulkanDevice *device); private: @@ -424,7 +424,7 @@ inline bool ImageBuilder::isFormatSupported(VulkanDevice *device) return true; } -inline std::unique_ptr ImageBuilder::create(VulkanDevice *device) +inline std::unique_ptr ImageBuilder::create(VulkanDevice *device, VkDeviceSize* allocatedBytes) { VkImage image; VmaAllocation allocation; @@ -433,6 +433,14 @@ inline std::unique_ptr 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(device, image, allocation, imageInfo.extent.width, imageInfo.extent.height, imageInfo.mipLevels); } diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index be94b747a..755e3a8dc 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -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); } }