summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-10-23 09:28:58 -0400
committerGitHub <noreply@github.com>2019-10-23 09:28:58 -0400
commit9c2d1766ea33101b551ac521ddc39516b98b6641 (patch)
treefeee466c977575ebcb15b9057a59c2efce5d9ae1 /source
parent6a7f4c9cef766e538a808a8f03411af2f10106e1 (diff)
Expose more repro in API, support output params. (#1087)
* Added spEnableReproCapture to the API. * Added MemoryStreamBase - which can be used to read from without copyin the data. Added the missing Repro API functions - spEnableReproCapture and spExtractRepro. Added support for serializing output filenames. * Improved naming around Stream. Brought Stream and sub types closer to code conventions. * Renamed content -> contents in Stream.
Diffstat (limited to 'source')
-rw-r--r--source/core/slang-io.cpp4
-rw-r--r--source/core/slang-riff.cpp14
-rw-r--r--source/core/slang-stream.cpp478
-rw-r--r--source/core/slang-stream.h255
-rw-r--r--source/core/slang-text-io.cpp14
-rw-r--r--source/core/slang-text-io.h6
-rw-r--r--source/slang/slang-compiler.h13
-rw-r--r--source/slang/slang-file-system.cpp2
-rw-r--r--source/slang/slang-ir-serialize.cpp42
-rw-r--r--source/slang/slang-options.cpp2
-rw-r--r--source/slang/slang-state-serialize.cpp102
-rw-r--r--source/slang/slang-state-serialize.h8
-rw-r--r--source/slang/slang.cpp65
13 files changed, 591 insertions, 414 deletions
diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp
index caa45c8f4..6cff8e1c9 100644
--- a/source/core/slang-io.cpp
+++ b/source/core/slang-io.cpp
@@ -660,10 +660,10 @@ namespace Slang
{
RefPtr<FileStream> fs = new FileStream(fileName, FileMode::Open, FileAccess::Read, FileShare::ReadWrite);
List<unsigned char> buffer;
- while (!fs->IsEnd())
+ while (!fs->isEnd())
{
unsigned char ch;
- int read = (int)fs->Read(&ch, 1);
+ int read = (int)fs->read(&ch, 1);
if (read)
buffer.add(ch);
else
diff --git a/source/core/slang-riff.cpp b/source/core/slang-riff.cpp
index df2076013..ce8b7129b 100644
--- a/source/core/slang-riff.cpp
+++ b/source/core/slang-riff.cpp
@@ -20,7 +20,7 @@ namespace Slang
}
// Skip the payload (we don't need to skip the Chunk because that was already read
- stream->Seek(SeekOrigin::Current, chunkSize - sizeof(RiffChunk));
+ stream->seek(SeekOrigin::Current, chunkSize - sizeof(RiffChunk));
return SLANG_OK;
}
@@ -29,7 +29,7 @@ namespace Slang
{
try
{
- stream->Read(&outChunk, sizeof(RiffChunk));
+ stream->read(&outChunk, sizeof(RiffChunk));
}
catch (IOException&)
{
@@ -53,13 +53,13 @@ namespace Slang
try
{
- out->Write(&chunk, sizeof(chunk));
- out->Write(data, size);
+ out->write(&chunk, sizeof(chunk));
+ out->write(data, size);
size_t remaining = size & 3;
if (remaining)
{
uint8_t end[4] = { 0, 0, 0, 0};
- out->Write(end, 4 - remaining);
+ out->write(end, 4 - remaining);
}
}
catch (IOException&)
@@ -79,13 +79,13 @@ namespace Slang
try
{
- stream->Read(data.getBuffer(), outChunk.m_size);
+ stream->read(data.getBuffer(), outChunk.m_size);
// Skip to the alignment
uint32_t remaining = outChunk.m_size & 3;
if (remaining)
{
- stream->Seek(SeekOrigin::Current, 4 - remaining);
+ stream->seek(SeekOrigin::Current, 4 - remaining);
}
}
catch (IOException&)
diff --git a/source/core/slang-stream.cpp b/source/core/slang-stream.cpp
index ee194c451..b5eef1d9b 100644
--- a/source/core/slang-stream.cpp
+++ b/source/core/slang-stream.cpp
@@ -6,289 +6,301 @@
namespace Slang
{
- FileStream::FileStream(const Slang::String & fileName, FileMode fileMode)
- {
- Init(fileName, fileMode, fileMode==FileMode::Open?FileAccess::Read:FileAccess::Write, FileShare::None);
- }
- FileStream::FileStream(const Slang::String & fileName, FileMode fileMode, FileAccess access, FileShare share)
- {
- Init(fileName, fileMode, access, share);
- }
- void FileStream::Init(const Slang::String & fileName, FileMode fileMode, FileAccess access, FileShare share)
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! FileStream !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+FileStream::FileStream(const String& fileName, FileMode fileMode)
+{
+ _init(fileName, fileMode, fileMode==FileMode::Open?FileAccess::Read:FileAccess::Write, FileShare::None);
+}
+
+FileStream::FileStream(const String& fileName, FileMode fileMode, FileAccess access, FileShare share)
+{
+ _init(fileName, fileMode, access, share);
+}
+
+void FileStream::_init(const String& fileName, FileMode fileMode, FileAccess access, FileShare share)
+{
+ const wchar_t * mode = L"rt";
+ const char* modeMBCS = "rt";
+ switch (fileMode)
{
- const wchar_t * mode = L"rt";
- const char* modeMBCS = "rt";
- switch (fileMode)
+ case FileMode::Create:
+ if (access == FileAccess::Read)
+ throw ArgumentException("Read-only access is incompatible with Create mode.");
+ else if (access == FileAccess::ReadWrite)
{
- case Slang::FileMode::Create:
- if (access == FileAccess::Read)
- throw ArgumentException("Read-only access is incompatible with Create mode.");
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"w+b";
- modeMBCS = "w+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"wb";
- modeMBCS = "wb";
- this->fileAccess = FileAccess::Write;
- }
- break;
- case Slang::FileMode::Open:
- if (access == FileAccess::Read)
- {
- mode = L"rb";
- modeMBCS = "rb";
- this->fileAccess = FileAccess::Read;
- }
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"r+b";
- modeMBCS = "r+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"wb";
- modeMBCS = "wb";
- this->fileAccess = FileAccess::Write;
- }
- break;
- case Slang::FileMode::CreateNew:
- if (File::exists(fileName))
- {
- throw IOException("Failed opening '" + fileName + "', file already exists.");
- }
- if (access == FileAccess::Read)
- throw ArgumentException("Read-only access is incompatible with Create mode.");
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"w+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"wb";
- this->fileAccess = FileAccess::Write;
- }
- break;
- case Slang::FileMode::Append:
- if (access == FileAccess::Read)
- throw ArgumentException("Read-only access is incompatible with Append mode.");
- else if (access == FileAccess::ReadWrite)
- {
- mode = L"a+b";
- this->fileAccess = FileAccess::ReadWrite;
- }
- else
- {
- mode = L"ab";
- this->fileAccess = FileAccess::Write;
- }
- break;
- default:
- break;
+ mode = L"w+b";
+ modeMBCS = "w+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
}
-#ifdef _WIN32
- int shFlag = _SH_DENYRW;
- switch (share)
+ else
{
- case Slang::FileShare::None:
- shFlag = _SH_DENYRW;
- break;
- case Slang::FileShare::ReadOnly:
- shFlag = _SH_DENYWR;
- break;
- case Slang::FileShare::WriteOnly:
- shFlag = _SH_DENYRD;
- break;
- case Slang::FileShare::ReadWrite:
- shFlag = _SH_DENYNO;
- break;
- default:
- throw ArgumentException("Invalid file share mode.");
- break;
+ mode = L"wb";
+ modeMBCS = "wb";
+ this->m_fileAccess = FileAccess::Write;
}
- if (share == Slang::FileShare::None)
-#pragma warning(suppress:4996)
- handle = _wfopen(fileName.toWString(), mode);
- else
- handle = _wfsopen(fileName.toWString(), mode, shFlag);
-#else
- handle = fopen(fileName.getBuffer(), modeMBCS);
-#endif
- if (!handle)
+ break;
+ case FileMode::Open:
+ if (access == FileAccess::Read)
+ {
+ mode = L"rb";
+ modeMBCS = "rb";
+ this->m_fileAccess = FileAccess::Read;
+ }
+ else if (access == FileAccess::ReadWrite)
+ {
+ mode = L"r+b";
+ modeMBCS = "r+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
+ }
+ else
{
- throw IOException("Cannot open file '" + fileName + "'");
+ mode = L"wb";
+ modeMBCS = "wb";
+ this->m_fileAccess = FileAccess::Write;
}
+ break;
+ case FileMode::CreateNew:
+ if (File::exists(fileName))
+ {
+ throw IOException("Failed opening '" + fileName + "', file already exists.");
+ }
+ if (access == FileAccess::Read)
+ throw ArgumentException("Read-only access is incompatible with Create mode.");
+ else if (access == FileAccess::ReadWrite)
+ {
+ mode = L"w+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
+ }
+ else
+ {
+ mode = L"wb";
+ this->m_fileAccess = FileAccess::Write;
+ }
+ break;
+ case FileMode::Append:
+ if (access == FileAccess::Read)
+ throw ArgumentException("Read-only access is incompatible with Append mode.");
+ else if (access == FileAccess::ReadWrite)
+ {
+ mode = L"a+b";
+ this->m_fileAccess = FileAccess::ReadWrite;
+ }
+ else
+ {
+ mode = L"ab";
+ this->m_fileAccess = FileAccess::Write;
+ }
+ break;
+ default:
+ break;
}
- FileStream::~FileStream()
+#ifdef _WIN32
+ int shFlag = _SH_DENYRW;
+ switch (share)
{
- Close();
+ case FileShare::None:
+ shFlag = _SH_DENYRW;
+ break;
+ case FileShare::ReadOnly:
+ shFlag = _SH_DENYWR;
+ break;
+ case FileShare::WriteOnly:
+ shFlag = _SH_DENYRD;
+ break;
+ case FileShare::ReadWrite:
+ shFlag = _SH_DENYNO;
+ break;
+ default:
+ throw ArgumentException("Invalid file share mode.");
+ break;
}
- Int64 FileStream::GetPosition()
+ if (share == FileShare::None)
+#pragma warning(suppress:4996)
+ m_handle = _wfopen(fileName.toWString(), mode);
+ else
+ m_handle = _wfsopen(fileName.toWString(), mode, shFlag);
+#else
+ m_handle = fopen(fileName.getBuffer(), modeMBCS);
+#endif
+ if (!m_handle)
{
+ throw IOException("Cannot open file '" + fileName + "'");
+ }
+}
+
+FileStream::~FileStream()
+{
+ close();
+}
+
+Int64 FileStream::getPosition()
+{
#if defined(_WIN32) || defined(__CYGWIN__)
- fpos_t pos;
- fgetpos(handle, &pos);
- return pos;
+ fpos_t pos;
+ fgetpos(m_handle, &pos);
+ return pos;
#elif defined(__APPLE__)
- return ftell(handle);
+ return ftell(m_handle);
#else
- fpos64_t pos;
- fgetpos64(handle, &pos);
- return *(Int64*)(&pos);
+ fpos64_t pos;
+ fgetpos64(m_handle, &pos);
+ return *(Int64*)(&pos);
#endif
- }
- void FileStream::Seek(SeekOrigin origin, Int64 offset)
+}
+void FileStream::seek(SeekOrigin origin, Int64 offset)
+{
+ int _origin;
+ switch (origin)
{
- int _origin;
- switch (origin)
- {
- case Slang::SeekOrigin::Start:
- _origin = SEEK_SET;
- endReached = false;
- break;
- case Slang::SeekOrigin::End:
- _origin = SEEK_END;
- // JS TODO: This doesn't seem right, the offset can mean it's not at the end
- endReached = true;
- break;
- case Slang::SeekOrigin::Current:
- _origin = SEEK_CUR;
- endReached = false;
- break;
- default:
- throw NotSupportedException("Unsupported seek origin.");
- break;
- }
+ case SeekOrigin::Start:
+ _origin = SEEK_SET;
+ m_endReached = false;
+ break;
+ case SeekOrigin::End:
+ _origin = SEEK_END;
+ // JS TODO: This doesn't seem right, the offset can mean it's not at the end
+ m_endReached = true;
+ break;
+ case SeekOrigin::Current:
+ _origin = SEEK_CUR;
+ m_endReached = false;
+ break;
+ default:
+ throw NotSupportedException("Unsupported seek origin.");
+ break;
+ }
#ifdef _WIN32
- int rs = _fseeki64(handle, offset, _origin);
+ int rs = _fseeki64(m_handle, offset, _origin);
#else
- int rs = fseek(handle, (int)offset, _origin);
+ int rs = fseek(m_handle, (int)offset, _origin);
#endif
- if (rs != 0)
- {
- throw IOException("FileStream seek failed.");
- }
- }
- Int64 FileStream::Read(void * buffer, Int64 length)
- {
- auto bytes = fread_s(buffer, (size_t)length, 1, (size_t)length, handle);
- if (bytes == 0 && length > 0)
- {
- if (!feof(handle))
- throw IOException("FileStream read failed.");
- else if (endReached)
- throw EndOfStreamException("End of file is reached.");
- endReached = true;
- }
- return (int)bytes;
- }
- Int64 FileStream::Write(const void * buffer, Int64 length)
- {
- auto bytes = (Int64)fwrite(buffer, 1, (size_t)length, handle);
- if (bytes < length)
- {
- throw IOException("FileStream write failed.");
- }
- return bytes;
- }
- bool FileStream::CanRead()
+ if (rs != 0)
{
- return ((int)fileAccess & (int)FileAccess::Read) != 0;
+ throw IOException("FileStream seek failed.");
}
- bool FileStream::CanWrite()
+}
+Int64 FileStream::read(void* buffer, Int64 length)
+{
+ auto bytes = fread_s(buffer, (size_t)length, 1, (size_t)length, m_handle);
+ if (bytes == 0 && length > 0)
{
- return ((int)fileAccess & (int)FileAccess::Write) != 0;
+ if (!feof(m_handle))
+ throw IOException("FileStream read failed.");
+ else if (m_endReached)
+ throw EndOfStreamException("End of file is reached.");
+ m_endReached = true;
}
- void FileStream::Close()
+ return (int)bytes;
+}
+Int64 FileStream::write(const void* buffer, Int64 length)
+{
+ auto bytes = (Int64)fwrite(buffer, 1, (size_t)length, m_handle);
+ if (bytes < length)
{
- if (handle)
- {
- fclose(handle);
- handle = 0;
- }
+ throw IOException("FileStream write failed.");
}
- bool FileStream::IsEnd()
+ return bytes;
+}
+bool FileStream::canRead()
+{
+ return ((int)m_fileAccess & (int)FileAccess::Read) != 0;
+}
+bool FileStream::canWrite()
+{
+ return ((int)m_fileAccess & (int)FileAccess::Write) != 0;
+}
+void FileStream::close()
+{
+ if (m_handle)
{
- return endReached;
+ fclose(m_handle);
+ m_handle = 0;
}
+}
+bool FileStream::isEnd()
+{
+ return m_endReached;
+}
- // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MemoryStream !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MemoryStreamBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- void MemoryStream::Seek(SeekOrigin origin, Int64 offset)
+void MemoryStreamBase::seek(SeekOrigin origin, Int64 offset)
+{
+ Int64 pos = 0;
+ switch (origin)
{
- Int64 pos = 0;
- switch (origin)
- {
- case Slang::SeekOrigin::Start:
+ case SeekOrigin::Start:
pos = offset;
break;
- case Slang::SeekOrigin::End:
- pos = Int64(m_contents.getCount()) + offset;
+ case SeekOrigin::End:
+ pos = Int64(m_contentsSize) + offset;
break;
- case Slang::SeekOrigin::Current:
+ case SeekOrigin::Current:
pos = Int64(m_position) + offset;
break;
default:
throw NotSupportedException("Unsupported seek origin.");
break;
- }
+ }
- m_atEnd = false;
+ m_atEnd = false;
- // Clamp to the valid range
- pos = (pos < 0) ? 0 : pos;
- pos = (pos > Int64(m_contents.getCount())) ? Int64(m_contents.getCount()) : pos;
+ // Clamp to the valid range
+ pos = (pos < 0) ? 0 : pos;
+ pos = (pos > Int64(m_contentsSize)) ? Int64(m_contentsSize) : pos;
- m_position = UInt(pos);
+ m_position = UInt(pos);
+}
+
+Int64 MemoryStreamBase::read(void* buffer, Int64 length)
+{
+ if (!canRead())
+ {
+ throw IOException("Cannot read this stream.");
}
- Int64 MemoryStream::Read(void * buffer, Int64 length)
+ const Int64 maxRead = Int64(m_contentsSize - m_position);
+
+ if (maxRead == 0 && length > 0)
{
- if (!CanRead())
- {
- throw IOException("Cannot read this stream.");
- }
+ m_atEnd = true;
+ throw EndOfStreamException("End of file is reached.");
+ }
- const Int64 maxRead = Int64(m_contents.getCount() - m_position);
-
- if (maxRead == 0 && length > 0)
- {
- m_atEnd = true;
- throw EndOfStreamException("End of file is reached.");
- }
+ length = length > maxRead ? maxRead : length;
- length = length > maxRead ? maxRead : length;
+ ::memcpy(buffer, m_contents + m_position, size_t(length));
+ m_position += UInt(length);
+ return maxRead;
+}
- ::memcpy(buffer, m_contents.begin() + m_position, size_t(length));
- m_position += UInt(length);
- return maxRead;
- }
-
- Int64 MemoryStream::Write(const void * buffer, Int64 length)
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! OwnedMemoryStream !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+Int64 OwnedMemoryStream::write(const void * buffer, Int64 length)
+{
+ if (!canWrite())
{
- if (!CanWrite())
- {
- throw IOException("Cannot write this stream.");
- }
+ throw IOException("Cannot write this stream.");
+ }
- if (m_position == m_contents.getCount())
- {
- m_contents.addRange((const uint8_t*)buffer, UInt(length));
- }
- else
- {
- m_contents.insertRange(m_position, (const uint8_t*)buffer, UInt(length));
- }
+ if (m_position == m_ownedContents.getCount())
+ {
+ m_ownedContents.addRange((const uint8_t*)buffer, UInt(length));
+ }
+ else
+ {
+ m_ownedContents.insertRange(m_position, (const uint8_t*)buffer, UInt(length));
+ }
- m_atEnd = false;
+ m_contents = m_ownedContents.getBuffer();
+ m_contentsSize = ptrdiff_t(m_ownedContents.getCount());
- m_position += UInt(length);
- return length;
- }
+ m_atEnd = false;
+ m_position += ptrdiff_t(length);
+ return length;
}
+
+} // namespace Slang
diff --git a/source/core/slang-stream.h b/source/core/slang-stream.h
index 67e04fa6a..8b8a6decf 100644
--- a/source/core/slang-stream.h
+++ b/source/core/slang-stream.h
@@ -5,109 +5,170 @@
namespace Slang
{
- class IOException : public Exception
- {
- public:
- IOException()
- {}
- IOException(const String & message)
- : Slang::Exception(message)
- {
- }
- };
-
- class EndOfStreamException : public IOException
- {
- public:
- EndOfStreamException()
- {}
- EndOfStreamException(const String & message)
- : IOException(message)
- {
- }
- };
-
- enum class SeekOrigin
- {
- Start, End, Current
- };
- class Stream : public RefObject
- {
- public:
- virtual ~Stream() {}
- virtual Int64 GetPosition()=0;
- virtual void Seek(SeekOrigin origin, Int64 offset)=0;
- virtual Int64 Read(void * buffer, Int64 length) = 0;
- virtual Int64 Write(const void * buffer, Int64 length) = 0;
- virtual bool IsEnd() = 0;
- virtual bool CanRead() = 0;
- virtual bool CanWrite() = 0;
- virtual void Close() = 0;
- };
-
- enum class FileMode
+class IOException : public Exception
+{
+public:
+ IOException()
+ {}
+ IOException(const String & message)
+ : Slang::Exception(message)
{
- Create, Open, CreateNew, Append
- };
+ }
+};
- enum class FileAccess
+class EndOfStreamException : public IOException
+{
+public:
+ EndOfStreamException()
+ {}
+ EndOfStreamException(const String & message)
+ : IOException(message)
{
- None = 0, Read = 1, Write = 2, ReadWrite = 3
- };
+ }
+};
- enum class FileShare
- {
- None, ReadOnly, WriteOnly, ReadWrite
- };
+enum class SeekOrigin
+{
+ Start, End, Current
+};
+
+class Stream : public RefObject
+{
+public:
+ virtual ~Stream() {}
+ virtual Int64 getPosition()=0;
+ virtual void seek(SeekOrigin origin, Int64 offset)=0;
+ virtual Int64 read(void * buffer, Int64 length) = 0;
+ virtual Int64 write(const void * buffer, Int64 length) = 0;
+ virtual bool isEnd() = 0;
+ virtual bool canRead() = 0;
+ virtual bool canWrite() = 0;
+ virtual void close() = 0;
+};
+
+enum class FileMode
+{
+ Create, Open, CreateNew, Append
+};
+
+enum class FileAccess
+{
+ None = 0, Read = 1, Write = 2, ReadWrite = 3
+};
- class MemoryStream : public Stream
+enum class FileShare
+{
+ None, ReadOnly, WriteOnly, ReadWrite
+};
+
+/// Base class for memory streams. Only supports reading and does NOT own contained data.
+class MemoryStreamBase : public Stream
+{
+public:
+ typedef Stream Super;
+
+ virtual Int64 getPosition() SLANG_OVERRIDE { return m_position; }
+ virtual void seek(SeekOrigin origin, Int64 offset) SLANG_OVERRIDE;
+ virtual Int64 read(void * buffer, Int64 length) SLANG_OVERRIDE;
+ virtual Int64 write(const void * buffer, Int64 length) SLANG_OVERRIDE { SLANG_UNUSED(buffer); SLANG_UNUSED(length); return 0; }
+ virtual bool isEnd() SLANG_OVERRIDE { return m_atEnd; }
+ virtual bool canRead() SLANG_OVERRIDE { return (int(m_access) & int(FileAccess::Read)) != 0; }
+ virtual bool canWrite() SLANG_OVERRIDE { return (int(m_access) & int(FileAccess::Write)) != 0; }
+ virtual void close() SLANG_OVERRIDE { m_access = FileAccess::None; }
+
+ MemoryStreamBase(FileAccess access = FileAccess::Read, const void* contents = nullptr, size_t contentsSize = 0):
+ m_access(access)
{
- public:
- virtual Int64 GetPosition() SLANG_OVERRIDE { return m_position; }
- virtual void Seek(SeekOrigin origin, Int64 offset) SLANG_OVERRIDE;
- virtual Int64 Read(void * buffer, Int64 length) SLANG_OVERRIDE;
- virtual Int64 Write(const void * buffer, Int64 length) SLANG_OVERRIDE;
- virtual bool IsEnd() SLANG_OVERRIDE { return m_atEnd; }
- virtual bool CanRead() SLANG_OVERRIDE { return (int(m_access) & int(FileAccess::Read)) != 0; }
- virtual bool CanWrite() SLANG_OVERRIDE { return (int(m_access) & int(FileAccess::Write)) != 0; }
- virtual void Close() SLANG_OVERRIDE { m_access = FileAccess::None; }
-
- MemoryStream(FileAccess access) :
- m_access(access),
- m_position(0),
- m_atEnd(false)
- {}
-
- Index m_position;
-
- bool m_atEnd; ///< Happens when a read is done and nothing can be returned because already at end
-
- FileAccess m_access;
- List<uint8_t> m_contents;
- };
-
- class FileStream : public Stream
- {
- private:
- FILE * handle;
- FileAccess fileAccess;
- bool endReached = false;
- void Init(const Slang::String & fileName, FileMode fileMode, FileAccess access, FileShare share);
- public:
- FileStream(const Slang::String & fileName, FileMode fileMode = FileMode::Open);
- FileStream(const Slang::String & fileName, FileMode fileMode, FileAccess access, FileShare share);
- ~FileStream();
- public:
- virtual Int64 GetPosition();
- virtual void Seek(SeekOrigin origin, Int64 offset);
- virtual Int64 Read(void * buffer, Int64 length);
- virtual Int64 Write(const void * buffer, Int64 length);
- virtual bool CanRead();
- virtual bool CanWrite();
- virtual void Close();
- virtual bool IsEnd();
- };
-}
+ _setContents(contents, contentsSize);
+ }
+
+protected:
+ /// Set to replace wholly current content with specified content
+ void _setContents(const void* contents, size_t contentsSize)
+ {
+ m_contents = (const uint8_t*)contents;
+ m_contentsSize = ptrdiff_t(contentsSize);
+ m_position = 0;
+ m_atEnd = false;
+ }
+ /// Update means that the content has changed, but position should be maintained
+ void _updateContents(const void* contents, size_t contentsSize)
+ {
+ const ptrdiff_t newPosition = (m_position > ptrdiff_t(contentsSize)) ? ptrdiff_t(contentsSize) : m_position;
+ _setContents(contents, contentsSize);
+ m_position = newPosition;
+ }
+
+ const uint8_t* m_contents; ///< The content held in the stream
+
+ // Using ptrdiff_t (as opposed to size_t) as makes maths simpler
+ ptrdiff_t m_contentsSize; ///< Total size of the content in bytes
+ ptrdiff_t m_position; ///< The current position within content (valid values can only be between 0 and m_contentSize)
+
+ bool m_atEnd; ///< Happens when a read is done and nothing can be returned because already at end
+
+ FileAccess m_access;
+};
+
+/// Memory stream that owns it's contents
+class OwnedMemoryStream : public MemoryStreamBase
+{
+public:
+ typedef MemoryStreamBase Super;
+
+ virtual Int64 write(const void* buffer, Int64 length) SLANG_OVERRIDE;
+
+ /// Set the contents
+ void setContent(const void* contents, size_t contentsSize)
+ {
+ m_ownedContents.setCount(contentsSize);
+ ::memcpy(m_ownedContents.getBuffer(), contents, contentsSize);
+ _setContents(m_ownedContents.getBuffer(), m_ownedContents.getCount());
+ }
+
+ void swapContents(List<uint8_t>& rhs)
+ {
+ rhs.swapWith(m_ownedContents);
+ _setContents(m_ownedContents.getBuffer(), m_ownedContents.getCount());
+ }
+
+ OwnedMemoryStream(FileAccess access) :
+ Super(access)
+ {}
+
+protected:
+
+ List<uint8_t> m_ownedContents;
+};
+
+class FileStream : public Stream
+{
+public:
+ typedef Stream Super;
+
+ // Stream interface
+ virtual Int64 getPosition();
+ virtual void seek(SeekOrigin origin, Int64 offset);
+ virtual Int64 read(void* buffer, Int64 length);
+ virtual Int64 write(const void* buffer, Int64 length);
+ virtual bool canRead();
+ virtual bool canWrite();
+ virtual void close();
+ virtual bool isEnd();
+
+ FileStream(const String& fileName, FileMode fileMode = FileMode::Open);
+ FileStream(const String& fileName, FileMode fileMode, FileAccess access, FileShare share);
+ ~FileStream();
+
+private:
+ void _init(const String& fileName, FileMode fileMode, FileAccess access, FileShare share);
+
+ FILE* m_handle;
+ FileAccess m_fileAccess;
+ bool m_endReached = false;
+};
+
+} // namespace Slang
#endif
diff --git a/source/core/slang-text-io.cpp b/source/core/slang-text-io.cpp
index 18039e41b..4e989b627 100644
--- a/source/core/slang-text-io.cpp
+++ b/source/core/slang-text-io.cpp
@@ -126,11 +126,11 @@ namespace Slang
this->encoding = encoding;
if (encoding == Encoding::UTF16)
{
- this->stream->Write(&Utf16Header, 2);
+ this->stream->write(&Utf16Header, 2);
}
else if (encoding == Encoding::UTF16Reversed)
{
- this->stream->Write(&Utf16ReversedHeader, 2);
+ this->stream->write(&Utf16ReversedHeader, 2);
}
}
StreamWriter::StreamWriter(RefPtr<Stream> stream, Encoding * encoding)
@@ -139,11 +139,11 @@ namespace Slang
this->encoding = encoding;
if (encoding == Encoding::UTF16)
{
- this->stream->Write(&Utf16Header, 2);
+ this->stream->write(&Utf16Header, 2);
}
else if (encoding == Encoding::UTF16Reversed)
{
- this->stream->Write(&Utf16ReversedHeader, 2);
+ this->stream->write(&Utf16ReversedHeader, 2);
}
}
void StreamWriter::Write(const String & str)
@@ -169,7 +169,7 @@ namespace Slang
sb << str[i];
}
encoding->GetBytes(encodingBuffer, sb.ProduceString());
- stream->Write(encodingBuffer.getBuffer(), encodingBuffer.getCount());
+ stream->write(encodingBuffer.getBuffer(), encodingBuffer.getCount());
}
void StreamWriter::Write(const char * str)
{
@@ -237,7 +237,7 @@ namespace Slang
{
buffer.setCount(4096);
memset(buffer.getBuffer(), 0, buffer.getCount() * sizeof(buffer[0]));
- auto len = stream->Read(buffer.getBuffer(), buffer.getCount());
+ auto len = stream->read(buffer.getBuffer(), buffer.getCount());
buffer.setCount((int)len);
ptr = 0;
}
@@ -248,7 +248,7 @@ namespace Slang
{
return buffer[ptr++];
}
- if (!stream->IsEnd())
+ if (!stream->isEnd())
ReadBuffer();
if (ptr<buffer.getCount())
{
diff --git a/source/core/slang-text-io.h b/source/core/slang-text-io.h
index ac9a4f5dc..b5a9ad0e1 100644
--- a/source/core/slang-text-io.h
+++ b/source/core/slang-text-io.h
@@ -259,7 +259,7 @@ namespace Slang
virtual void Write(const char * str);
virtual void Close()
{
- stream->Close();
+ stream->close();
}
void ReleaseStream()
{
@@ -300,11 +300,11 @@ namespace Slang
virtual String ReadToEnd();
virtual bool IsEnd()
{
- return ptr == buffer.getCount() && stream->IsEnd();
+ return ptr == buffer.getCount() && stream->isEnd();
}
virtual void Close()
{
- stream->Close();
+ stream->close();
}
void ReleaseStream()
{
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index 9b361064d..1e1f166de 100644
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -1172,17 +1172,19 @@ namespace Slang
/// If this member is `null`, a default implementation that tries
/// to use the native OS filesystem will be used instead.
///
- ComPtr<ISlangFileSystem> fileSystem;
+ ComPtr<ISlangFileSystem> m_fileSystem;
/// The extended file system implementation. Will be set to a default implementation
/// if fileSystem is nullptr. Otherwise it will either be fileSystem's interface,
/// or a wrapped impl that makes fileSystem operate as fileSystemExt
- ComPtr<ISlangFileSystemExt> fileSystemExt;
+ ComPtr<ISlangFileSystemExt> m_fileSystemExt;
+
/// Set if fileSystemExt is a cache file system
- RefPtr<CacheFileSystem> cacheFileSystem;
+ RefPtr<CacheFileSystem> m_cacheFileSystem;
- ISlangFileSystemExt* getFileSystemExt() { return fileSystemExt; }
+ ISlangFileSystemExt* getFileSystemExt() { return m_fileSystemExt; }
+ CacheFileSystem* getCacheFileSystem() const { return m_cacheFileSystem; }
/// Load a file into memory using the configured file system.
///
@@ -1192,7 +1194,6 @@ namespace Slang
///
SlangResult loadFile(String const& path, PathInfo& outPathInfo, ISlangBlob** outBlob);
-
RefPtr<Expr> parseTypeString(String typeStr, RefPtr<Scope> scope);
Type* specializeType(
@@ -1230,7 +1231,7 @@ namespace Slang
return m_sourceManager;
}
- /// Override the source manager for the linakge.
+ /// Override the source manager for the linkage.
///
/// This is only used to install a temporary override when
/// parsing stuff from strings (where we don't want to retain
diff --git a/source/slang/slang-file-system.cpp b/source/slang/slang-file-system.cpp
index 4ee961df5..7d6d6df66 100644
--- a/source/slang/slang-file-system.cpp
+++ b/source/slang/slang-file-system.cpp
@@ -138,7 +138,7 @@ SLANG_NO_THROW SlangResult SLANG_MCALL OSFileSystemExt::saveFile(const char* pat
{
FileStream stream(pathIn, FileMode::Create, FileAccess::Write, FileShare::ReadWrite);
- int64_t numWritten = stream.Write(data, size);
+ int64_t numWritten = stream.write(data, size);
if (numWritten != int64_t(size))
{
diff --git a/source/slang/slang-ir-serialize.cpp b/source/slang/slang-ir-serialize.cpp
index 02ed3142d..c82592527 100644
--- a/source/slang/slang-ir-serialize.cpp
+++ b/source/slang/slang-ir-serialize.cpp
@@ -847,9 +847,9 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
header.m_chunk.m_size = uint32_t(payloadSize);
header.m_numEntries = uint32_t(numEntries);
- stream->Write(&header, sizeof(header));
+ stream->write(&header, sizeof(header));
- stream->Write(data, typeSize * numEntries);
+ stream->write(data, typeSize * numEntries);
break;
}
case Bin::CompressionType::VariableByteLite:
@@ -868,9 +868,9 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
header.m_numEntries = uint32_t(numEntries);
header.m_numCompressedEntries = uint32_t(numCompressedEntries);
- stream->Write(&header, sizeof(header));
+ stream->write(&header, sizeof(header));
- stream->Write(compressedPayload.begin(), compressedPayload.getCount());
+ stream->write(compressedPayload.begin(), compressedPayload.getCount());
break;
}
default:
@@ -884,7 +884,7 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
const uint8_t pad[4] = { 0, 0, 0, 0 };
// Pad outs
int padSize = 4 - (payloadSize & 3);
- stream->Write(pad, padSize);
+ stream->write(pad, padSize);
}
return SLANG_OK;
@@ -1013,8 +1013,8 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin
header.m_numEntries = uint32_t(array.getCount());
header.m_numCompressedEntries = 0;
- stream->Write(&header, sizeof(header));
- stream->Write(compressedPayload.begin(), compressedPayload.getCount());
+ stream->write(&header, sizeof(header));
+ stream->write(compressedPayload.begin(), compressedPayload.getCount());
// All chunks have sizes rounded to dword size
if (payloadSize & 3)
@@ -1022,7 +1022,7 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin
const uint8_t pad[4] = { 0, 0, 0, 0 };
// Pad outs
int padSize = 4 - (payloadSize & 3);
- stream->Write(pad, padSize);
+ stream->write(pad, padSize);
}
return SLANG_OK;
}
@@ -1128,7 +1128,7 @@ static size_t _calcInstChunkSize(IRSerialBinary::CompressionType compressionType
riffHeader.m_type = Bin::kRiffFourCc;
riffHeader.m_size = uint32_t(totalSize);
- stream->Write(&riffHeader, sizeof(riffHeader));
+ stream->write(&riffHeader, sizeof(riffHeader));
}
{
Bin::SlangHeader slangHeader;
@@ -1136,7 +1136,7 @@ static size_t _calcInstChunkSize(IRSerialBinary::CompressionType compressionType
slangHeader.m_chunk.m_size = uint32_t(sizeof(slangHeader) - sizeof(RiffChunk));
slangHeader.m_compressionType = uint32_t(Bin::CompressionType::VariableByteLite);
- stream->Write(&slangHeader, sizeof(slangHeader));
+ stream->write(&slangHeader, sizeof(slangHeader));
}
SLANG_RETURN_ON_FAIL(_writeInstArrayChunk(compressionType, Bin::kInstFourCc, data.m_insts, stream));
@@ -1206,7 +1206,7 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, c
Bin::CompressedArrayHeader header;
header.m_chunk = chunk;
- stream->Read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
+ stream->read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
*numReadInOut += sizeof(header) - sizeof(RiffChunk);
void* data = listOut.setSize(header.m_numEntries);
@@ -1217,7 +1217,7 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, c
List<uint8_t> compressedPayload;
compressedPayload.setCount(payloadSize);
- stream->Read(compressedPayload.begin(), payloadSize);
+ stream->read(compressedPayload.begin(), payloadSize);
*numReadInOut += payloadSize;
SLANG_ASSERT(header.m_numCompressedEntries == uint32_t((header.m_numEntries * typeSize) / sizeof(uint32_t)));
@@ -1232,14 +1232,14 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, c
Bin::ArrayHeader header;
header.m_chunk = chunk;
- stream->Read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
+ stream->read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
*numReadInOut += sizeof(header) - sizeof(RiffChunk);
const size_t payloadSize = header.m_numEntries * typeSize;
void* data = listOut.setSize(header.m_numEntries);
- stream->Read(data, payloadSize);
+ stream->read(data, payloadSize);
*numReadInOut += payloadSize;
break;
}
@@ -1251,7 +1251,7 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, c
const uint8_t pad[4] = { 0, 0, 0, 0 };
// Pad outs
int padSize = 4 - int(*numReadInOut & 3);
- stream->Seek(SeekOrigin::Current, padSize);
+ stream->seek(SeekOrigin::Current, padSize);
*numReadInOut += padSize;
}
@@ -1374,7 +1374,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::SlangHeader& slangHeader
Bin::CompressedArrayHeader header;
header.m_chunk = chunk;
- stream->Read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
+ stream->read(&header.m_chunk + 1, sizeof(header) - sizeof(RiffChunk));
*numReadInOut += sizeof(header) - sizeof(RiffChunk);
// Need to read all the compressed data...
@@ -1383,7 +1383,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::SlangHeader& slangHeader
List<uint8_t> compressedPayload;
compressedPayload.setCount(payloadSize);
- stream->Read(compressedPayload.begin(), payloadSize);
+ stream->read(compressedPayload.begin(), payloadSize);
*numReadInOut += payloadSize;
arrayOut.setCount(header.m_numEntries);
@@ -1402,7 +1402,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::SlangHeader& slangHeader
{
// Pad outs
int padSize = 4 - int(*numReadInOut & 3);
- stream->Seek(SeekOrigin::Current, padSize);
+ stream->seek(SeekOrigin::Current, padSize);
*numReadInOut += padSize;
}
@@ -1449,7 +1449,7 @@ static Result _readInstArrayChunk(const IRSerialBinary::SlangHeader& slangHeader
// NOTE! Really we should only read what we know the size to be...
// and skip if it's larger
- stream->Read(&slangHeader.m_chunk + 1, sizeof(slangHeader) - sizeof(chunk));
+ stream->read(&slangHeader.m_chunk + 1, sizeof(slangHeader) - sizeof(chunk));
remainingBytes -= RiffUtil::calcChunkTotalSize(chunk);
break;
@@ -1964,11 +1964,11 @@ static int _calcFixSourceLoc(const IRSerialData::DebugSourceInfo& info, SourceVi
}
// Write the data out to stream
- MemoryStream memoryStream(FileAccess::ReadWrite);
+ OwnedMemoryStream memoryStream(FileAccess::ReadWrite);
SLANG_RETURN_ON_FAIL(IRSerialWriter::writeStream(serialData, compressionType, &memoryStream));
// Reset stream
- memoryStream.Seek(SeekOrigin::Start, 0);
+ memoryStream.seek(SeekOrigin::Start, 0);
IRSerialData readData;
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 2e1b625d9..6b09179db 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -496,7 +496,7 @@ struct OptionsParser
else if (argStr == "-dump-repro")
{
SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, requestImpl->dumpRepro));
- requestImpl->getLinkage()->setRequireCacheFileSystem(true);
+ spEnableReproCapture(asExternal(requestImpl));
}
else if (argStr == "-extract-repro")
{
diff --git a/source/slang/slang-state-serialize.cpp b/source/slang/slang-state-serialize.cpp
index b37529121..110ea52b2 100644
--- a/source/slang/slang-state-serialize.cpp
+++ b/source/slang/slang-state-serialize.cpp
@@ -318,15 +318,49 @@ static bool _isStorable(const PathInfo::Type type)
for (Index i = 0; i < linkage->targets.getCount(); ++i)
{
- auto& dst = dstTargets[i];
- TargetRequest* targetRequest = linkage->targets[i];
+ TargetRequest* srcTargetRequest = linkage->targets[i];
- dst.target = targetRequest->getTarget();
- dst.profile = targetRequest->getTargetProfile();
- dst.targetFlags = targetRequest->targetFlags;
- dst.floatingPointMode = targetRequest->floatingPointMode;
- }
+ // Copy the simple stuff
+ {
+ auto& dst = dstTargets[i];
+ dst.target = srcTargetRequest->getTarget();
+ dst.profile = srcTargetRequest->getTargetProfile();
+ dst.targetFlags = srcTargetRequest->targetFlags;
+ dst.floatingPointMode = srcTargetRequest->floatingPointMode;
+ }
+
+ // Copy the entry point/target output names
+ {
+ const auto& srcTargetInfos = request->targetInfos;
+
+ if (RefPtr<EndToEndCompileRequest::TargetInfo>* infosPtr = srcTargetInfos.TryGetValue(srcTargetRequest))
+ {
+ EndToEndCompileRequest::TargetInfo* infos = *infosPtr;
+
+ const auto& entryPointOutputPaths = infos->entryPointOutputPaths;
+
+ Safe32Array<OutputState> dstOutputStates;
+ dstOutputStates = inOutContainer.allocateArray<OutputState>(entryPointOutputPaths.Count());
+ Index index = 0;
+ for (const auto& pair : entryPointOutputPaths)
+ {
+ Safe32Ptr<RelativeString> outputPath = inOutContainer.newString(pair.Value.getUnownedSlice());
+
+ auto& dstOutputState = dstOutputStates[index];
+
+ dstOutputState.entryPointIndex = int32_t(pair.Key);
+ dstOutputState.outputPath = outputPath;
+
+ index++;
+ }
+
+ dstTargets[i].outputStates = dstOutputStates;
+ }
+ }
+ }
+
+ // Save the result
requestState->targetRequests = dstTargets;
}
@@ -383,7 +417,12 @@ static bool _isStorable(const PathInfo::Type type)
// Find files from the file system, and mapping paths to files
{
- CacheFileSystem* cacheFileSystem = linkage->cacheFileSystem;
+ CacheFileSystem* cacheFileSystem = linkage->getCacheFileSystem();
+ if (!cacheFileSystem)
+ {
+ return SLANG_FAIL;
+ }
+
// Traverse the references (in process we will construct the map from PathInfo)
{
const auto& srcFiles = cacheFileSystem->getPathMap();
@@ -651,8 +690,17 @@ static void _loadDefines(const Relative32Array<StateSerializeUtil::StringPair>&
{
auto externalRequest = asExternal(request);
+
auto linkage = request->getLinkage();
+ // TODO(JS): Really should be more exhaustive here, and set up to initial state ideally
+ // Reset state
+ {
+ request->targetInfos.Clear();
+ // Remove any requests
+ linkage->targets.clear();
+ }
+
LoadContext context(linkage->getSourceManager(), fileSystem);
// Try to set state through API - as doing so means if state stored in multiple places it will be ok
@@ -671,20 +719,41 @@ static void _loadDefines(const Relative32Array<StateSerializeUtil::StringPair>&
linkage->setMatrixLayoutMode(requestState->defaultMatrixLayoutMode);
}
+
+ // Add the target requests
{
for (Index i = 0; i < requestState->targetRequests.getCount(); ++i)
{
TargetRequestState& src = requestState->targetRequests[i];
int index = spAddCodeGenTarget(externalRequest, SlangCompileTarget(src.target));
- SLANG_UNUSED(index);
SLANG_ASSERT(index == i);
- auto dstTarget = linkage->targets[i];
+ auto dstTarget = linkage->targets[index];
SLANG_ASSERT(dstTarget->getTarget() == src.target);
dstTarget->targetProfile = src.profile;
dstTarget->targetFlags = src.targetFlags;
dstTarget->floatingPointMode = src.floatingPointMode;
+
+ // If there is output state (like output filenames) add here
+ if (src.outputStates.getCount())
+ {
+ RefPtr<EndToEndCompileRequest::TargetInfo> dstTargetInfo(new EndToEndCompileRequest::TargetInfo);
+ request->targetInfos[dstTarget] = dstTargetInfo;
+
+ for (const auto& srcOutputState : src.outputStates)
+ {
+ SLANG_ASSERT(srcOutputState.entryPointIndex < requestState->entryPoints.getCount());
+
+ String entryPointPath;
+ if (srcOutputState.outputPath)
+ {
+ entryPointPath = srcOutputState.outputPath->getSlice();
+ }
+
+ dstTargetInfo->entryPointOutputPaths.Add(srcOutputState.entryPointIndex, entryPointPath);
+ }
+ }
}
}
@@ -744,6 +813,9 @@ static void _loadDefines(const Relative32Array<StateSerializeUtil::StringPair>&
// Entry points
{
+ // Check there aren't any set entry point
+ SLANG_ASSERT(request->getFrontEndReq()->m_entryPointReqs.getCount() == 0);
+
for (const auto& srcEntryPoint : requestState->entryPoints)
{
const char* name = srcEntryPoint.name ? srcEntryPoint.name->getCstr() : nullptr;
@@ -782,8 +854,8 @@ static void _loadDefines(const Relative32Array<StateSerializeUtil::StringPair>&
// This is a bit of a hack, we are going to replace the file system, with our one which is filled in
// with what was read from the file.
- linkage->fileSystemExt = cacheFileSystem;
- linkage->cacheFileSystem = cacheFileSystem;
+ linkage->m_fileSystemExt = cacheFileSystem;
+ linkage->m_cacheFileSystem = cacheFileSystem;
}
return SLANG_OK;
@@ -834,11 +906,7 @@ static void _loadDefines(const Relative32Array<StateSerializeUtil::StringPair>&
/* static */SlangResult StateSerializeUtil::loadState(const uint8_t* data, size_t size, List<uint8_t>& outBuffer)
{
- MemoryStream stream(FileAccess::Read);
-
- stream.m_contents.setCount(size);
- ::memcpy(stream.m_contents.getBuffer(), data, size);
-
+ MemoryStreamBase stream(FileAccess::Read, data, size);
return loadState(&stream, outBuffer);
}
diff --git a/source/slang/slang-state-serialize.h b/source/slang/slang-state-serialize.h
index f43cc8d45..dbd1e3992 100644
--- a/source/slang/slang-state-serialize.h
+++ b/source/slang/slang-state-serialize.h
@@ -52,6 +52,12 @@ struct StateSerializeUtil
Relative32Ptr<PathInfoState> pathInfo;
};
+ struct OutputState
+ {
+ int32_t entryPointIndex;
+ Relative32Ptr<RelativeString> outputPath;
+ };
+
// spSetCodeGenTarget/spAddCodeGenTarget
// spSetTargetProfile
// spSetTargetFlags
@@ -63,6 +69,8 @@ struct StateSerializeUtil
CodeGenTarget target;
SlangTargetFlags targetFlags;
FloatingPointMode floatingPointMode;
+
+ Relative32Array<OutputState> outputStates;
};
struct FileReference
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 19ac6ea1f..8479d3202 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -800,11 +800,11 @@ SlangResult Linkage::loadFile(String const& path, PathInfo& outPathInfo, ISlangB
{
outPathInfo.type = PathInfo::Type::Unknown;
- SLANG_RETURN_ON_FAIL(fileSystemExt->loadFile(path.getBuffer(), outBlob));
+ SLANG_RETURN_ON_FAIL(m_fileSystemExt->loadFile(path.getBuffer(), outBlob));
ComPtr<ISlangBlob> uniqueIdentity;
// Get the unique identity
- SLANG_RETURN_ON_FAIL(fileSystemExt->getFileUniqueIdentity(path.getBuffer(), uniqueIdentity.writeRef()));
+ SLANG_RETURN_ON_FAIL(m_fileSystemExt->getFileUniqueIdentity(path.getBuffer(), uniqueIdentity.writeRef()));
outPathInfo.foundPath = path;
outPathInfo.type = PathInfo::Type::FoundPath;
@@ -2489,17 +2489,17 @@ static const Slang::Guid IID_SlangCacheFileSystem = SLANG_UUID_CacheFileSystem;
void Linkage::setFileSystem(ISlangFileSystem* inFileSystem)
{
// Set the fileSystem
- fileSystem = inFileSystem;
+ m_fileSystem = inFileSystem;
// Release what's there
- fileSystemExt.setNull();
- cacheFileSystem.setNull();
+ m_fileSystemExt.setNull();
+ m_cacheFileSystem.setNull();
// If nullptr passed in set up default
if (inFileSystem == nullptr)
{
- cacheFileSystem = new Slang::CacheFileSystem(Slang::OSFileSystemExt::getSingleton());
- fileSystemExt = cacheFileSystem;
+ m_cacheFileSystem = new Slang::CacheFileSystem(Slang::OSFileSystemExt::getSingleton());
+ m_fileSystemExt = m_cacheFileSystem;
}
else
{
@@ -2507,34 +2507,34 @@ void Linkage::setFileSystem(ISlangFileSystem* inFileSystem)
inFileSystem->queryInterface(IID_SlangCacheFileSystem, (void**)&cacheFileSystemPtr);
if (cacheFileSystemPtr)
{
- cacheFileSystem = cacheFileSystemPtr;
- fileSystemExt = cacheFileSystemPtr;
+ m_cacheFileSystem = cacheFileSystemPtr;
+ m_fileSystemExt = cacheFileSystemPtr;
}
else
{
if (m_requireCacheFileSystem)
{
- cacheFileSystem = new Slang::CacheFileSystem(inFileSystem);
- fileSystemExt = cacheFileSystem;
+ m_cacheFileSystem = new Slang::CacheFileSystem(inFileSystem);
+ m_fileSystemExt = m_cacheFileSystem;
}
else
{
// See if we have the full ISlangFileSystemExt interface, if we do just use it
- inFileSystem->queryInterface(IID_ISlangFileSystemExt, (void**)fileSystemExt.writeRef());
+ inFileSystem->queryInterface(IID_ISlangFileSystemExt, (void**)m_fileSystemExt.writeRef());
// If not wrap with CacheFileSystem that emulates ISlangFileSystemExt from the ISlangFileSystem interface
- if (!fileSystemExt)
+ if (!m_fileSystemExt)
{
// Construct a wrapper to emulate the extended interface behavior
- cacheFileSystem = new Slang::CacheFileSystem(fileSystem);
- fileSystemExt = cacheFileSystem;
+ m_cacheFileSystem = new Slang::CacheFileSystem(m_fileSystem);
+ m_fileSystemExt = m_cacheFileSystem;
}
}
}
}
// Set the file system used on the source manager
- getSourceManager()->setFileSystemExt(fileSystemExt);
+ getSourceManager()->setFileSystemExt(m_fileSystemExt);
}
void Linkage::setRequireCacheFileSystem(bool requireCacheFileSystem)
@@ -2544,7 +2544,7 @@ void Linkage::setRequireCacheFileSystem(bool requireCacheFileSystem)
return;
}
- ComPtr<ISlangFileSystem> scopeFileSystem(fileSystem);
+ ComPtr<ISlangFileSystem> scopeFileSystem(m_fileSystem);
m_requireCacheFileSystem = requireCacheFileSystem;
setFileSystem(scopeFileSystem);
@@ -3478,17 +3478,44 @@ SLANG_API SlangResult spSaveRepro(
using namespace Slang;
auto request = asInternal(inRequest);
- MemoryStream stream(FileAccess::Write);
+ OwnedMemoryStream stream(FileAccess::Write);
SLANG_RETURN_ON_FAIL(StateSerializeUtil::saveState(request, &stream));
RefPtr<ListBlob> listBlob(new ListBlob);
- listBlob->m_data.swapWith(stream.m_contents);
+
+ // Put the content of the stream in the blob
+ stream.swapContents(listBlob->m_data);
*outBlob = listBlob.detach();
return SLANG_OK;
}
+SLANG_API SlangResult spEnableReproCapture(
+ SlangCompileRequest* inRequest)
+{
+ using namespace Slang;
+ auto request = asInternal(inRequest);
+
+ request->getLinkage()->setRequireCacheFileSystem(true);
+ return SLANG_OK;
+}
+
+SLANG_API SlangResult spExtractRepro(SlangSession* session, const void* reproData, size_t reproDataSize, ISlangFileSystemExt* fileSystem)
+{
+ using namespace Slang;
+ SLANG_UNUSED(session);
+
+ List<uint8_t> buffer;
+ {
+ MemoryStreamBase memoryStream(FileAccess::Read, reproData, reproDataSize);
+ SLANG_RETURN_ON_FAIL(StateSerializeUtil::loadState(&memoryStream, buffer));
+ }
+
+ StateSerializeUtil::RequestState* requestState = StateSerializeUtil::getRequest(buffer);
+ return StateSerializeUtil::extractFiles(requestState, fileSystem);
+}
+
// Reflection API
SLANG_API SlangResult spCompileRequest_getProgram(