From fb34c1861df395d2b206363bd2cd7c8edfce6c06 Mon Sep 17 00:00:00 2001
From: baldurk <baldurk@baldurk.org>
Date: Fri, 19 May 2023 09:58:49 +0100
Subject: Don't call ReadLargeBuffer for socket reads

* In ReadLargeBuffer we read directly into an external buffer with ReadExternal,
  but for sockets when reading externally we want to read ahead of the current
  spot (non-blocking) as much as possible to batch small reads together. Rather
  than making ReadExternal handle or detect reads to external buffers, we
  instead avoid ReadLargeBuffer as it is an optimisation for direct I/O to avoid
  unnecessary memcpy's and is not relevant for sockets.
---
 renderdoc/serialise/streamio.cpp | 11 ++++++++++-
 renderdoc/serialise/streamio.h   |  4 +++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/renderdoc/serialise/streamio.cpp b/renderdoc/serialise/streamio.cpp
index 5669c2c01..ebddd33c8 100644
--- a/renderdoc/serialise/streamio.cpp
+++ b/renderdoc/serialise/streamio.cpp
@@ -270,7 +270,7 @@ bool StreamReader::Reserve(uint64_t numBytes)
 
 bool StreamReader::ReadLargeBuffer(void *buffer, uint64_t length)
 {
-  RDCASSERT(m_Sock || m_File || m_Decompressor);
+  RDCASSERT(m_File || m_Decompressor);
 
   byte *dest = (byte *)buffer;
 
@@ -398,6 +398,9 @@ bool StreamReader::ReadFromExternal(void *buffer, uint64_t length)
       // first get the required data blocking (this will sleep the thread until it comes in).
       byte *readDest = (byte *)buffer;
 
+      // we expect to be reading into our window buffer
+      RDCASSERT(readDest >= m_BufferBase && readDest <= m_BufferBase + m_BufferSize);
+
       success = m_Sock->RecvDataBlocking(readDest, (uint32_t)length);
 
       if(success)
@@ -407,6 +410,12 @@ bool StreamReader::ReadFromExternal(void *buffer, uint64_t length)
 
         uint32_t bufSize = uint32_t(m_BufferSize - m_InputSize);
 
+        if(m_InputSize > m_BufferSize)
+        {
+          bufSize = 0;
+          RDCERR("Invalid read in ReadFromExternal!");
+        }
+
         // now read more, as much as possible, to try and batch future reads
         success = m_Sock->RecvDataNonBlocking(readDest, bufSize);
 
diff --git a/renderdoc/serialise/streamio.h b/renderdoc/serialise/streamio.h
index ec7b53a8a..8b296b876 100644
--- a/renderdoc/serialise/streamio.h
+++ b/renderdoc/serialise/streamio.h
@@ -180,7 +180,9 @@ public:
         // and larger by just skating over the limit each time, but that's fine because the main
         // case we want to catch is a window that's only a few MB and then suddenly we read 100s of
         // MB.
-        if(numBytes >= 10 * 1024 * 1024 && Available() + 128 < numBytes)
+        // We don't do this on sockets since we want to opportunistically read more into the window
+        // to batch lots of small reads together.
+        if(m_Sock == NULL && numBytes >= 10 * 1024 * 1024 && Available() + 128 < numBytes)
         {
           success = ReadLargeBuffer(data, numBytes);
           alreadyread = true;
-- 
2.30.2

