texture data on DirectX has some extra bytes that we need to remove before sending data

This commit is contained in:
bernatx 2023-01-13 16:27:25 +01:00 committed by bernat
parent 5f233585eb
commit cba2231977
3 changed files with 39 additions and 25 deletions

View File

@ -66,7 +66,7 @@ public:
{
if (HeaderStr->frame != FrameNumber)
{
carla::log_debug("Re-framing sensor type ", HeaderStr->sensor_type, " from ", HeaderStr->frame, " to ", FrameNumber);
carla::log_info("Re-framing sensor type ", HeaderStr->sensor_type, " from ", HeaderStr->frame, " to ", FrameNumber);
HeaderStr->frame = FrameNumber;
}
}

View File

@ -12,27 +12,6 @@
#include "HighResScreenshot.h"
#include "Runtime/ImageWriteQueue/Public/ImageWriteQueue.h"
// =============================================================================
// -- Local variables and types ------------------------------------------------
// =============================================================================
struct LockTexture
{
LockTexture(FRHITexture2D *InTexture, uint32 &Stride)
: Texture(InTexture),
Source(reinterpret_cast<const uint8 *>(
RHILockTexture2D(Texture, 0, RLM_ReadOnly, Stride, false))) {}
~LockTexture()
{
RHIUnlockTexture2D(Texture, 0, false);
}
FRHITexture2D *Texture;
const uint8 *Source;
};
// =============================================================================
// -- FPixelReader -------------------------------------------------------------
// =============================================================================
@ -86,11 +65,12 @@ void FPixelReader::WritePixelsToBuffer(
}
FPixelFormatInfo PixelFormat = GPixelFormats[BackBufferPixelFormat];
uint32 ExpectedRowBytes = BackBufferSize.X * PixelFormat.BlockBytes;
int32 Size = (BackBufferSize.Y * (PixelFormat.BlockBytes * BackBufferSize.X));
void* LockedData = Readback->Lock(Size);
if (LockedData)
{
FuncForSending(LockedData, Size, Offset);
FuncForSending(LockedData, Size, Offset, ExpectedRowBytes);
}
Readback->Unlock();
Readback.reset();

View File

@ -10,6 +10,11 @@
#include "Engine/TextureRenderTarget2D.h"
#include "Runtime/ImageWriteQueue/Public/ImagePixelData.h"
#ifdef PLATFORM_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <D3d12.h>
#endif
#include "Carla/Game/CarlaEngine.h"
#include <compiler/disable-ue4-macros.h>
@ -29,7 +34,7 @@ class FPixelReader
{
public:
using Payload = std::function<void(void *, uint32, uint32)>;
using Payload = std::function<void(void *, uint32, uint32, uint32)>;
/// Copy the pixels in @a RenderTarget into @a BitMap.
///
@ -111,7 +116,7 @@ void FPixelReader::SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat
if (!Sensor.IsPendingKill())
{
FPixelReader::Payload FuncForSending =
[&Sensor, Frame = FCarlaEngine::GetFrameCounter(), Conversor = std::move(Conversor)](void *LockedData, uint32 Size, uint32 Offset)
[&Sensor, Frame = FCarlaEngine::GetFrameCounter(), Conversor = std::move(Conversor)](void *LockedData, uint32 Size, uint32 Offset, uint32 ExpectedRowBytes)
{
if (Sensor.IsPendingKill()) return;
@ -129,11 +134,40 @@ void FPixelReader::SendPixelsInRenderThread(TSensor &Sensor, bool use16BitFormat
auto Stream = Sensor.GetDataStream(Sensor);
Stream.SetFrameNumber(Frame);
auto Buffer = Stream.PopBufferFromPool();
uint32 CurrentRowBytes = ExpectedRowBytes;
#ifdef PLATFORM_WINDOWS
// DirectX uses additional bytes to align each row to 256 boundry,
// so we need to remove that extra data
if (IsD3DPlatform(GMaxRHIShaderPlatform, false))
{
CurrentRowBytes = Align(ExpectedRowBytes, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
if (ExpectedRowBytes != CurrentRowBytes)
{
TRACE_CPUPROFILER_EVENT_SCOPE_STR("Buffer Copy (windows, row by row)");
Buffer.reset(Offset + Size);
auto DstRow = Buffer.begin() + Offset;
const uint8 *SrcRow = reinterpret_cast<uint8 *>(LockedData);
uint32 i = 0;
while (i < Size)
{
FMemory::Memcpy(DstRow, SrcRow, ExpectedRowBytes);
DstRow += ExpectedRowBytes;
SrcRow += CurrentRowBytes;
i += ExpectedRowBytes;
}
}
}
#endif // PLATFORM_WINDOWS
if (ExpectedRowBytes == CurrentRowBytes)
{
check(ExpectedRowBytes == CurrentRowBytes);
TRACE_CPUPROFILER_EVENT_SCOPE_STR("Buffer Copy");
Buffer.copy_from(Offset, boost::asio::buffer(LockedData, Size));
}
{
// send
TRACE_CPUPROFILER_EVENT_SCOPE_STR("Sending buffer");