Finished first version of shader compiler. HLSL -> DXIL.

Submitting vertex and frag shader needed to display a triangle.
This commit is contained in:
2025-03-08 22:36:15 -05:00
parent f9f292b6d6
commit da203c80f3
27 changed files with 837 additions and 173 deletions

View File

@@ -20,7 +20,7 @@ using size_t = std::size_t;
struct ByteBuffer
{
const Byte* Data;
Byte* Data;
size_t Size;
};

View File

@@ -1,9 +1,10 @@
#pragma once
#include <algorithm>
#include <Core/Common/CoreTypes.h>
#include <Juliet.h>
#include <algorithm>
namespace Juliet
{
@@ -24,8 +25,6 @@ namespace Juliet
extern void JULIET_API JulietAssert(const char* expression);
#define DEFER(cleanup) for (bool done_ = 0; !done_; (cleanup), done_ = 1)
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
#define ZeroArray(array) ZeroSize(sizeof((array)), (array))
#define ZeroDynArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), Pointer)
@@ -38,8 +37,44 @@ namespace Juliet
}
}
#define MemCopy memcpy
template <class Function>
class DeferredFunction
{
public:
explicit DeferredFunction(const Function& otherFct) noexcept
: Callback(otherFct)
{
}
explicit DeferredFunction(Function&& otherFct) noexcept
: Callback(std::move(otherFct))
{
}
~DeferredFunction() noexcept { Callback(); }
DeferredFunction(const DeferredFunction&) = delete;
DeferredFunction(const DeferredFunction&&) = delete;
void operator=(const DeferredFunction&) = delete;
void operator=(DeferredFunction&&) = delete;
private:
Function Callback;
};
template <class Function>
auto Defer(Function&& fct) noexcept
{
return DeferredFunction<std::decay_t<Function>>{ std::forward<Function>(fct) };
}
inline bool IsValid(ByteBuffer buffer)
{
return buffer.Size > 0 && buffer.Data;
}
extern JULIET_API void Free(ByteBuffer& buffer);
// TODO move to math utils
template <typename Type>
constexpr Type Min(Type lhs, Type rhs)
{

View File

@@ -33,6 +33,13 @@ namespace Juliet
size_t Size;
};
struct StringBuffer : String
{
size_t Capacity;
};
constexpr uint32 kInvalidUTF8 = 0xFFFD;
inline size_t StringLength(String str)
{
return str.Size;
@@ -56,7 +63,7 @@ namespace Juliet
return length;
}
inline bool StringIsValid(String str)
inline bool IsValid(String str)
{
return str.Size > 0 && str.Data != nullptr && *str.Data;
}
@@ -89,7 +96,7 @@ namespace Juliet
inline bool ContainsChar(String str, char c)
{
return StringIsValid(FindChar(str, c));
return IsValid(FindChar(str, c));
}
// Return:
@@ -117,6 +124,9 @@ namespace Juliet
return result;
}
JULIET_API uint32 StepUTF8(String& inStr);
JULIET_API String FindString(String strLeft, String strRight);
// Case insensitive compare. Supports ASCII only
// TODO: Support UNICODE
extern JULIET_API int8 StringCompareCaseInsensitive(String str1, String str2);
@@ -127,10 +137,8 @@ namespace Juliet
// src and dst will be casted based on the encoding.
// size will correspond to the number of characters
// Will convert \0 character if present.
extern JULIET_API bool ConvertString(StringEncoding from, StringEncoding to, const char* src, size_t srcLen,
char*& dst, size_t& dstLen, size_t dstCapacity);
extern JULIET_API bool ConvertString(String from, String to, const char* src, size_t srcLen, char*& dst,
size_t& dstLen, size_t dstCapacity);
extern JULIET_API bool ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer& dst);
extern JULIET_API bool ConvertString(String from, String to, String src, StringBuffer& dst);
} // namespace Juliet

View File

@@ -41,7 +41,7 @@ namespace Juliet
int64 (*Seek)(NonNullPtr<IOStreamDataPayload> data, int64 offset, IOStreamSeekPivot pivot);
size_t (*Read)(NonNullPtr<IOStreamDataPayload> data, void* outBuffer, size_t size, NonNullPtr<IOStreamStatus> status);
size_t (*Write)(NonNullPtr<IOStreamDataPayload> data, const void* inBuffer, size_t size, NonNullPtr<IOStreamStatus> status);
size_t (*Write)(NonNullPtr<IOStreamDataPayload> data, ByteBuffer inBuffer, NonNullPtr<IOStreamStatus> status);
bool (*Flush)(NonNullPtr<IOStreamDataPayload> data, NonNullPtr<IOStreamStatus> status);
bool (*Close)(NonNullPtr<IOStreamDataPayload> data);
@@ -54,7 +54,7 @@ namespace Juliet
// Write formatted string into the stream.
extern JULIET_API size_t IOPrintf(NonNullPtr<IOStream> stream, _Printf_format_string_ const char* format, ...);
extern JULIET_API size_t IOWrite(NonNullPtr<IOStream> stream, const void* ptr, size_t size);
extern JULIET_API size_t IOWrite(NonNullPtr<IOStream> stream, ByteBuffer inBuffer);
extern JULIET_API size_t IORead(NonNullPtr<IOStream> stream, void* ptr, size_t size);
extern JULIET_API int64 IOSeek(NonNullPtr<IOStream> stream, int64 offset, IOStreamSeekPivot pivot);
@@ -62,8 +62,8 @@ namespace Juliet
extern JULIET_API int64 IOSize(NonNullPtr<IOStream> stream);
// TODO : Use memory arena because that Allocates
extern JULIET_API uint8* LoadFile(String filename, size_t& outByteRead);
extern JULIET_API uint8* LoadFile(NonNullPtr<IOStream> stream, size_t& outByteRead, bool closeStreamWhenDone);
extern JULIET_API ByteBuffer LoadFile(String filename);
extern JULIET_API ByteBuffer LoadFile(NonNullPtr<IOStream> stream, bool closeStreamWhenDone);
extern JULIET_API bool IOClose(NonNullPtr<IOStream> stream);
} // namespace Juliet

View File

@@ -35,7 +35,7 @@ namespace Juliet
std::deque<Entry> Entries;
bool IsInitialized : 1;
friend void Log(LogLevel level, LogCategory category, const char* fmt, ...);
friend void Log(LogLevel level, LogCategory category, const char* fmt, va_list args);
void AddEntry(Entry&& entry);
static void OutputLog(Entry& entry);
};
@@ -43,4 +43,7 @@ namespace Juliet
extern void JULIET_API InitializeLogManager();
extern void JULIET_API ShutdownLogManager();
extern void JULIET_API Log(LogLevel level, LogCategory category, const char* fmt, ...);
extern void JULIET_API LogMessage(LogCategory category, const char* fmt, ...);
extern void JULIET_API LogWarning(LogCategory category, const char* fmt, ...);
extern void JULIET_API LogError(LogCategory category, const char* fmt, ...);
} // namespace Juliet

View File

@@ -15,7 +15,7 @@ namespace Juliet
Graphics = 1,
Networking = 2,
Engine = 3,
Editor = 4,
Tool = 4,
Game = 5,
};
} // namespace Juliet

View File

@@ -1,6 +1,8 @@
#pragma once
#include <memory>
#include <Juliet.h>
#include <cstdlib>
namespace Juliet
{
@@ -15,7 +17,7 @@ namespace Juliet
void Free(Type* memory)
{
Assert(memory);
free(memory);
::free(memory);
}
// Free and Set the ptr to nullptr
template <typename Type>
@@ -23,7 +25,7 @@ namespace Juliet
{
if (memory)
{
free(memory);
::free(memory);
memory = nullptr;
}
}

View File

@@ -19,4 +19,5 @@ namespace Juliet
}
#define MemSet memset
#define MemCopy memcpy
} // namespace Juliet

View File

@@ -21,7 +21,7 @@ namespace Juliet
// Pack
NetworkPacket& operator<<(uint32 value);
NetworkPacket& operator<<(const char* data);
NetworkPacket& operator<<(char* data);
protected:
void Append(ByteBuffer buffer);

View File

@@ -1,10 +1,21 @@
#include <pch.h>
#include <Core/Memory/Allocator.h>
namespace Juliet
{
void JulietAssert(const char* expression)
{
Juliet::Log(Juliet::LogLevel::Error, Juliet::LogCategory::Core, expression);
Log(LogLevel::Error, LogCategory::Core, expression);
__debugbreak();
}
void Free(ByteBuffer& buffer)
{
if (buffer.Data)
{
Free(buffer.Data);
}
buffer = {};
}
} // namespace Juliet

View File

@@ -7,7 +7,6 @@ namespace Juliet
{
namespace
{
constexpr char kUnknown_ASCII = '?';
constexpr int32 kUnknown_UNICODE = 0xFFFD;
struct
@@ -57,52 +56,162 @@ namespace Juliet
*to = from;
return 1;
}
} // namespace
void Step(String& inStr, size_t byteToStep)
uint32 StepUTF8(String& inStr)
{
// From rfc3629, the UTF-8 spec:
// https://www.ietf.org/rfc/rfc3629.txt
//
// Char. number range | UTF-8 octet sequence
// (hexadecimal) | (binary)
// --------------------+---------------------------------------------
// 0000 0000-0000 007F | 0xxxxxxx
// 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
// 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
// 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
//
// The function checks character validity and overlong (using too many bytes to encode the character) and return invalid utf8 char if detected.
// If string is empty then it's done.
if (inStr.Size == 0)
{
Assert(inStr.Size >= byteToStep);
inStr.Data += byteToStep;
inStr.Size -= byteToStep;
}
uint32 StepUTF8(String& inStr, size_t byteToRead)
{
/*
* From rfc3629, the UTF-8 spec:
* https://www.ietf.org/rfc/rfc3629.txt
*
* Char. number range | UTF-8 octet sequence
* (hexadecimal) | (binary)
* --------------------+---------------------------------------------
* 0000 0000-0000 007F | 0xxxxxxx
* 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
* 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
* 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
*/
// If string is empty then it's done.
if (inStr.Size == 0)
{
return 0;
}
auto str = reinterpret_cast<const uint8*>(CStr(inStr));
const uint32 octet = byteToRead ? *str : 0;
if (octet == 0)
{
return 0;
}
if ((octet & 0x80) == 0x0) // One byte code point
{
Step(inStr, 1);
return octet;
}
Assert(false && "StepUTF8 only supports one byte codepoints for now");
return 0;
}
} // namespace
auto str = reinterpret_cast<const uint8*>(CStr(inStr));
const uint32 octet = *str;
bool isOverlong = false;
bool isInvalid = false;
bool isUTF16Surrogate = false;
if (octet == 0)
{
return 0;
}
if ((octet & 0x80) == 0x0) // One byte code point: 0xxxxxxx
{
inStr.Data += 1;
inStr.Size -= 1;
return octet;
}
else if ((octet & 0xE0) == 0xC0) // Two bytes code point: 110xxxxx 10xxxxxx
{
const uint8 secondByte = str[1];
if ((secondByte & 0xC0) == 0x80) // Make sure the trailing byte is correct
{
const uint32 result = ((octet & 0x1F) << 6) | (secondByte & 0x3F);
if (result >= 0x80) // If the result is smaller than 0x80 its an overlong!
{
inStr.Data += 2;
inStr.Size -= 1;
return result;
}
else
{
isOverlong = true;
}
}
else
{
isInvalid = true;
}
}
else if (((octet & 0xF0) == 0xE0)) // Three bytes code point: 1110xxxx 10xxxxxx 10xxxxxx
{
const uint8 secondByte = str[1];
const uint8 thirdByte = str[2];
if (((secondByte & 0xC0) == 0x80) && ((thirdByte & 0xC0) == 0x80)) // Make sure the trailing bytes are correct
{
const uint32 secondOctet = static_cast<uint32>(secondByte & 0x3F) << 6;
const uint32 thirdOctet = static_cast<uint32>(thirdByte & 0x3F);
const uint32 result = ((octet & 0x0F) << 12) | secondOctet | thirdOctet;
if (result >= 0x0800) // if the result is smaller its an overlong.
{
if ((result < 0xD800) || (result > 0xDFFF)) // If out of range its an UTF-16 surrogate
{
inStr.Data += 3;
inStr.Size -= 1;
return result;
}
else
{
isUTF16Surrogate = true;
}
}
else
{
isOverlong = true;
}
}
else
{
isInvalid = true;
}
}
else if (((octet & 0xF8) == 0xF0))
{ // Four bytes code point: 11110xxxx 10xxxxxx 10xxxxxx 10xxxxxx
const uint8 secondByte = str[1];
const uint8 thirdByte = str[2];
const uint8 fourthByte = str[3];
if (((secondByte & 0xC0) == 0x80) && ((thirdByte & 0xC0) == 0x80) &&
((fourthByte & 0xC0) == 0x80)) // // Make sure the trailing bytes are correct
{
const uint32 secondOctet = static_cast<uint32>(secondByte & 0x1F) << 12;
const uint32 thirdOctet = static_cast<uint32>(thirdByte & 0x3F) << 6;
const uint32 fourthOctet = static_cast<uint32>(fourthByte & 0x3F);
const uint32 result = ((octet & 0x07) << 18) | secondOctet | thirdOctet | fourthOctet;
if (result >= 0x10000) // If smaller its an overlong
{
inStr.Data += 4;
inStr.Size -= 1;
return result;
}
else
{
isOverlong = true;
}
}
else
{
isInvalid = true;
}
}
LogError(LogCategory::Core, "StepUTF8: Non supported codepoint. IsOverlong: %s. IsInvalid %s. IsUTF16Surrogate %s",
isOverlong ? "true" : "false", isInvalid ? "true" : "false", isUTF16Surrogate ? "true" : "false");
inStr.Data += 1;
return kInvalidUTF8;
}
String FindString(String haystack, String needle)
{
if (!IsValid(needle))
{
return haystack;
}
for (; IsValid(haystack); StepUTF8(haystack))
{
String tempHaystack = haystack;
String testNeedle = needle;
while (IsValid(tempHaystack) && IsValid(testNeedle))
{
uint32 codepointHaystack = StepUTF8(tempHaystack);
uint32 codepointNeedle = StepUTF8(testNeedle);
if (codepointHaystack != codepointNeedle)
{
break;
}
}
if (!IsValid(testNeedle))
{
return haystack;
}
}
return {};
}
int8 StringCompareCaseInsensitive(String str1, String str2)
{
@@ -113,13 +222,13 @@ namespace Juliet
{
{
uint32 leftFolded[3];
int8 num_folded = CaseFoldUnicode(StepUTF8(str1, 4), leftFolded);
int8 num_folded = CaseFoldUnicode(StepUTF8(str1), leftFolded);
Assert(num_folded == 1); // Only one uint32 codepoint supported for now (low ascii)
left = leftFolded[0];
}
{
uint32 rightFolded[3];
int8 num_folded = CaseFoldUnicode(StepUTF8(str2, 4), rightFolded);
int8 num_folded = CaseFoldUnicode(StepUTF8(str2), rightFolded);
Assert(num_folded == 1); // Only one uint32 codepoint supported for now (low ascii)
right = rightFolded[0];
}
@@ -139,15 +248,16 @@ namespace Juliet
return 0;
}
bool ConvertString(StringEncoding from, StringEncoding to, const char* src, size_t srcLen, char*& dst, size_t& dstLen, size_t dstCapacity)
bool ConvertString(StringEncoding from, StringEncoding to, String src, StringBuffer& dst)
{
Assert(src && *src);
Assert(IsValid(src));
const char* srcStr = src;
char* dstStr = dst;
const char* srcStr = src.Data;
char* dstStr = dst.Data;
size_t remainingCapacity = dst.Capacity;
uint32 character = 0;
while (srcLen > 0)
while (src.Size > 0)
{
// Decode in character
switch (from)
@@ -165,7 +275,7 @@ namespace Juliet
}
else
{
if (p[0] == 0xF0 && srcLen > 1 && (p[1] & 0xF0) == 0x80)
if (p[0] == 0xF0 && src.Size > 1 && (p[1] & 0xF0) == 0x80)
{
overlong = true;
}
@@ -181,7 +291,7 @@ namespace Juliet
}
else
{
if (p[0] == 0xE0 && srcLen > 1 && (p[1] & 0xE0) == 0x80)
if (p[0] == 0xE0 && src.Size > 1 && (p[1] & 0xE0) == 0x80)
{
overlong = true;
}
@@ -217,8 +327,8 @@ namespace Juliet
}
}
++srcStr;
--srcLen;
if (srcLen < left)
--src.Size;
if (src.Size < left)
{
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Failed to convert string. Incomplete input sequence");
return false;
@@ -234,7 +344,7 @@ namespace Juliet
character <<= 6;
character |= (p[0] & 0x3F);
++srcStr;
--srcLen;
--src.Size;
}
if (overlong)
{
@@ -268,7 +378,7 @@ namespace Juliet
}
if (character < 0x10000)
{
if (dstCapacity < 2)
if (remainingCapacity < 2)
{
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Destination buffer too short to fit UTF16");
return false;
@@ -277,12 +387,12 @@ namespace Juliet
p[0] = static_cast<uint8>(character);
dstStr += 2;
dstLen += 1;
dstCapacity -= 2;
dst.Size += 1;
remainingCapacity -= 2;
}
else
{
if (dstCapacity < 4)
if (remainingCapacity < 4)
{
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Destination buffer too short to fit UTF16");
return false;
@@ -296,8 +406,8 @@ namespace Juliet
p[2] = static_cast<uint8>(word2);
dstStr += 4;
dstLen += 1;
dstCapacity -= 4;
dst.Size += 1;
remainingCapacity -= 4;
}
break;
}
@@ -313,10 +423,10 @@ namespace Juliet
return true;
}
bool ConvertString(String from, String to, const char* src, size_t srcSize, char*& dst, size_t& dstSize, size_t dstCapacity)
bool ConvertString(String from, String to, String src, StringBuffer& dst)
{
Assert(StringIsValid(from));
Assert(StringIsValid(to));
Assert(IsValid(from));
Assert(IsValid(to));
// First find the encoding of the strings
auto sourceFormat = StringEncoding::Unknown;
@@ -346,6 +456,6 @@ namespace Juliet
return false;
}
return ConvertString(sourceFormat, destFormat, src, srcSize, dst, dstSize, dstCapacity);
return ConvertString(sourceFormat, destFormat, src, dst);
}
} // namespace Juliet

View File

@@ -15,7 +15,7 @@ namespace Juliet
String GetBasePath()
{
if (!StringIsValid(CachedBasePath))
if (!IsValid(CachedBasePath))
{
CachedBasePath = Platform::GetBasePath();
}
@@ -26,7 +26,7 @@ namespace Juliet
void ShutdownFilesystem()
{
if (StringIsValid(CachedBasePath))
if (IsValid(CachedBasePath))
{
CachedBasePath.Size = 0;
SafeFree(CachedBasePath.Data);

View File

@@ -11,12 +11,12 @@ namespace Juliet
{
IOStream* IOFromFile(String filename, String mode)
{
if (!StringIsValid(filename))
if (!IsValid(filename))
{
Log(LogLevel::Error, LogCategory::Core, "Trying to open IOStream on invalid filename");
return nullptr;
}
if (!StringIsValid(mode))
if (!IsValid(mode))
{
Log(LogLevel::Error, LogCategory::Core, "Trying to open IOStream with invalid mode");
return nullptr;
@@ -54,10 +54,11 @@ namespace Juliet
Assert(writtenSize >= 0);
return IOWrite(stream, formattedBuffer, static_cast<size_t>(writtenSize));
ByteBuffer buffer = {.Data = reinterpret_cast<Byte*>(formattedBuffer), .Size = static_cast<size_t>(writtenSize) };
return IOWrite(stream, buffer);
}
size_t IOWrite(NonNullPtr<IOStream> stream, const void* ptr, size_t size)
size_t IOWrite(NonNullPtr<IOStream> stream, ByteBuffer inBuffer)
{
if (!stream->Interface.Write)
{
@@ -68,12 +69,12 @@ namespace Juliet
stream->Status = IOStreamStatus::Ready;
if (size == 0)
if (!IsValid(inBuffer))
{
return 0;
}
size_t writtenBytes = stream->Interface.Write(stream->Data, ptr, size, &stream->Status);
size_t writtenBytes = stream->Interface.Write(stream->Data, inBuffer, &stream->Status);
if ((writtenBytes == 0) && (stream->Status == IOStreamStatus::Ready))
{
stream->Status = IOStreamStatus::Error;
@@ -131,23 +132,32 @@ namespace Juliet
return stream->Interface.Size(stream->Data);
}
uint8* LoadFile(String filename, size_t& outByteRead)
ByteBuffer LoadFile(String filename)
{
IOStream* stream = IOFromFile(filename, ConstString("rb"));
IOStream* stream = IOFromFile(filename, WrapString("rb"));
if (!stream)
{
outByteRead = 0;
return nullptr;
return {};
}
return LoadFile(stream, outByteRead, true);
return LoadFile(stream, true);
}
uint8* LoadFile(NonNullPtr<IOStream> stream, size_t& outByteRead, bool closeStreamWhenDone)
ByteBuffer LoadFile(NonNullPtr<IOStream> stream, bool closeStreamWhenDone)
{
constexpr size_t kFileChunkSize = 1024;
uint8* data = nullptr;
uint8* newData = nullptr;
size_t totalSize = 0;
ByteBuffer resultBuffer = {};
auto deferred = Defer(
[&]()
{
if (closeStreamWhenDone)
{
IOClose(stream);
}
});
// Try reading the size from the stream, if failing we'll try to read it chunk by chunk
bool loadChunks = false;
@@ -160,7 +170,7 @@ namespace Juliet
data = static_cast<uint8*>(Malloc(static_cast<size_t>(size + 1)));
if (!data)
{
goto done;
return {};
}
while (true)
@@ -174,8 +184,7 @@ namespace Juliet
if (!newData)
{
Free(data);
data = nullptr;
goto done;
return {};
}
data = newData;
}
@@ -201,14 +210,10 @@ namespace Juliet
// Adding null terminator
data[totalSize] = '\0';
done:
outByteRead = totalSize;
resultBuffer.Data = reinterpret_cast<Byte*>(data);
resultBuffer.Size = totalSize;
if (closeStreamWhenDone)
{
IOClose(stream);
}
return data;
return resultBuffer;
}
bool IOClose(NonNullPtr<IOStream> stream)

View File

@@ -131,7 +131,7 @@ namespace Juliet::Internal
return totalRead;
}
size_t FileWrite(NonNullPtr<IOStreamDataPayload> payload, const void* inBuffer, size_t size, NonNullPtr<IOStreamStatus> status)
size_t FileWrite(NonNullPtr<IOStreamDataPayload> payload, ByteBuffer inBuffer, NonNullPtr<IOStreamStatus> status)
{
auto win32Payload = static_cast<Win32IOStreamDataPayload*>(payload.Get());
DWORD bytes;
@@ -158,12 +158,12 @@ namespace Juliet::Internal
}
}
if (!WriteFile(win32Payload->Handle, inBuffer, static_cast<DWORD>(size), &bytes, nullptr))
if (!WriteFile(win32Payload->Handle, inBuffer.Data, static_cast<DWORD>(inBuffer.Size), &bytes, nullptr))
{
Log(LogLevel::Error, LogCategory::Core, "IoStream:FileWrite:Error writing to datastream: %d", GetLastError());
return 0;
}
if (bytes == 0 && size > 0)
if (bytes == 0 && inBuffer.Size > 0)
{
*status = IOStreamStatus::NotReady;
}
@@ -199,18 +199,17 @@ namespace Juliet::Internal
#if _DEBUG
// Making sure the mode is valid
String modeView = mode;
size_t modeLength = StringLength(modeView);
size_t modeLength = StringLength(mode);
Assert((modeLength <= 2) &&
"Mode should have at most 2 characters, one being either r,w or a and the other can only be +");
if (modeLength == 1)
{
Assert((modeView.Data[0] == 'r' || modeView.Data[0] == 'w' || modeView.Data[0] == 'a') &&
Assert((mode.Data[0] == 'r' || mode.Data[0] == 'w' || mode.Data[0] == 'a') &&
"Invalid Mode. First char is not r,w or a");
}
else
{
Assert((modeView.Data[1] == '+' || modeView.Data[1] == 'b') && "Invalid Mode. Second char is not +");
Assert((mode.Data[1] == '+' || mode.Data[1] == 'b') && "Invalid Mode. Second char is not +");
}
#endif
@@ -229,11 +228,12 @@ namespace Juliet::Internal
return nullptr;
}
// TODO: Detect when folder is missing and create it if in w or a mode.
HANDLE hFile = CreateFileA(CStr(filename), (canWrite | canRead), (canWrite) ? 0 : FILE_SHARE_READ, nullptr,
(openExisting | createAlways | openAlways), FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile == INVALID_HANDLE_VALUE)
{
Log(LogLevel::Error, LogCategory::Core, "IOFromFile: couldn't open %s", CStr(filename));
Log(LogLevel::Error, LogCategory::Core, "IOFromFile: couldn't open %s. Error: %d", CStr(filename), GetLastError());
return nullptr;
}

View File

@@ -87,15 +87,12 @@ namespace Juliet
LogManagerSingleton.Shutdown();
}
void Log(LogLevel level, LogCategory category, const char* fmt, ...)
void Log(LogLevel level, LogCategory category, const char* fmt, va_list args)
{
// TODO : Revisit, copy from https://github.com/Eclmist/Ether/blob/develop/src/common/logging/loggingmanager.cpp
char formattedBuffer[4096];
va_list args;
va_start(args, fmt);
(void)vsprintf_s(formattedBuffer, fmt, args); // Cast to void to ignore the return type. TODO : Juliet format function
va_end(args);
std::string formattedText(formattedBuffer);
@@ -114,4 +111,35 @@ namespace Juliet
}
}
void Log(LogLevel level, LogCategory category, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
Log(level, category, fmt, args);
va_end(args);
}
void LogMessage(LogCategory category, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
Log(LogLevel::Message, category, fmt, args);
va_end(args);
}
void LogWarning(LogCategory category, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
Log(LogLevel::Warning, category, fmt, args);
va_end(args);
}
void LogError(LogCategory category, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
Log(LogLevel::Error, category, fmt, args);
va_end(args);
}
} // namespace Juliet

View File

@@ -3,7 +3,7 @@
#include <Core/Networking/NetworkPacket.h>
#include <Core/Networking/SocketPlatformImpl.h>
#define TO_BUFFER(ptr) reinterpret_cast<const Byte*>(ptr)
#define TO_BUFFER(ptr) reinterpret_cast<Byte*>(ptr)
namespace Juliet
{
@@ -29,12 +29,12 @@ namespace Juliet
// Begin - Pack
NetworkPacket& NetworkPacket::operator<<(uint32 value)
{
const uint32 toWrite = htonl(value);
uint32 toWrite = htonl(value);
Append({ TO_BUFFER(&toWrite), sizeof(toWrite) });
return *this;
}
NetworkPacket& NetworkPacket::operator<<(const char* data)
NetworkPacket& NetworkPacket::operator<<(char* data)
{
Assert(data && "NetworkPacket::operator<< Data must not be null");

View File

@@ -1,6 +1,8 @@
#include <pch.h>
#include <Core/Memory/Allocator.h>
#include <Core/Memory/Utils.h>
#include <Graphics/D3D12/D3D12Common.h>
#include <Graphics/D3D12/DX12GraphicsDevice.h>
#include <Graphics/D3D12/DX12Includes.h>