Compare commits
3 Commits
67528aaee1
...
764824ff24
| Author | SHA1 | Date | |
|---|---|---|---|
| 764824ff24 | |||
| 09dc26ae79 | |||
| fc399d52ec |
@@ -114,9 +114,13 @@
|
|||||||
<ClInclude Include="include\Core\Common\NonMovable.h"/>
|
<ClInclude Include="include\Core\Common\NonMovable.h"/>
|
||||||
<ClInclude Include="include\Core\Common\NonNullPtr.h"/>
|
<ClInclude Include="include\Core\Common\NonNullPtr.h"/>
|
||||||
<ClInclude Include="include\Core\Common\Singleton.h"/>
|
<ClInclude Include="include\Core\Common\Singleton.h"/>
|
||||||
|
<ClInclude Include="include\Core\Common\String.h"/>
|
||||||
<ClInclude Include="include\Core\Container\Vector.h"/>
|
<ClInclude Include="include\Core\Container\Vector.h"/>
|
||||||
<ClInclude Include="include\Core\HAL\Display\Display.h"/>
|
<ClInclude Include="include\Core\HAL\Display\Display.h"/>
|
||||||
|
<ClInclude Include="include\Core\HAL\DynLib\DynamicLibrary.h"/>
|
||||||
<ClInclude Include="include\Core\HAL\Event\SystemEvent.h"/>
|
<ClInclude Include="include\Core\HAL\Event\SystemEvent.h"/>
|
||||||
|
<ClInclude Include="include\Core\HAL\Filesystem\Filesystem.h"/>
|
||||||
|
<ClInclude Include="include\Core\HAL\IO\IOStream.h"/>
|
||||||
<ClInclude Include="include\Core\HAL\Keyboard\Keyboard.h"/>
|
<ClInclude Include="include\Core\HAL\Keyboard\Keyboard.h"/>
|
||||||
<ClInclude Include="include\Core\HAL\Keyboard\KeyCode.h"/>
|
<ClInclude Include="include\Core\HAL\Keyboard\KeyCode.h"/>
|
||||||
<ClInclude Include="include\Core\HAL\Keyboard\ScanCode.h"/>
|
<ClInclude Include="include\Core\HAL\Keyboard\ScanCode.h"/>
|
||||||
@@ -156,6 +160,7 @@
|
|||||||
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h"/>
|
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h"/>
|
||||||
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Platform.h"/>
|
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Platform.h"/>
|
||||||
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Private.h"/>
|
<ClInclude Include="src\Core\HAL\Filesystem\Filesystem_Private.h"/>
|
||||||
|
<ClInclude Include="src\Core\HAL\IO\IOStream_Private.h"/>
|
||||||
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h"/>
|
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h"/>
|
||||||
<ClInclude Include="src\Core\HAL\Win32.h"/>
|
<ClInclude Include="src\Core\HAL\Win32.h"/>
|
||||||
<ClInclude Include="src\Graphics\D3D12\D3D12Common.h"/>
|
<ClInclude Include="src\Graphics\D3D12\D3D12Common.h"/>
|
||||||
@@ -173,6 +178,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\Core\Application\ApplicationManager.cpp"/>
|
<ClCompile Include="src\Core\Application\ApplicationManager.cpp"/>
|
||||||
<ClCompile Include="src\Core\Common\CoreUtils.cpp"/>
|
<ClCompile Include="src\Core\Common\CoreUtils.cpp"/>
|
||||||
|
<ClCompile Include="src\Core\Common\String.cpp" />
|
||||||
<ClCompile Include="src\Core\HAL\Display\Display.cpp"/>
|
<ClCompile Include="src\Core\HAL\Display\Display.cpp"/>
|
||||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayDevice.cpp"/>
|
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayDevice.cpp"/>
|
||||||
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.cpp"/>
|
<ClCompile Include="src\Core\HAL\Display\Win32\Win32DisplayEvent.cpp"/>
|
||||||
@@ -185,6 +191,8 @@
|
|||||||
<ClCompile Include="src\Core\HAL\Event\WindowEvent.cpp"/>
|
<ClCompile Include="src\Core\HAL\Event\WindowEvent.cpp"/>
|
||||||
<ClCompile Include="src\Core\HAL\Filesystem\Filesystem.cpp"/>
|
<ClCompile Include="src\Core\HAL\Filesystem\Filesystem.cpp"/>
|
||||||
<ClCompile Include="src\Core\HAL\Filesystem\Win32\Win32Filesystem.cpp"/>
|
<ClCompile Include="src\Core\HAL\Filesystem\Win32\Win32Filesystem.cpp"/>
|
||||||
|
<ClCompile Include="src\Core\HAL\IO\IOStream.cpp"/>
|
||||||
|
<ClCompile Include="src\Core\HAL\IO\Win32\Win32IOStream.cpp"/>
|
||||||
<ClCompile Include="src\Core\HotReload\HotReload.cpp"/>
|
<ClCompile Include="src\Core\HotReload\HotReload.cpp"/>
|
||||||
<ClCompile Include="src\Core\HotReload\Win32\Win32HotReload.cpp"/>
|
<ClCompile Include="src\Core\HotReload\Win32\Win32HotReload.cpp"/>
|
||||||
<ClCompile Include="src\Core\Juliet.cpp"/>
|
<ClCompile Include="src\Core\Juliet.cpp"/>
|
||||||
|
|||||||
@@ -24,14 +24,6 @@ struct ByteBuffer
|
|||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CharType>
|
|
||||||
struct StringBuffer
|
|
||||||
{
|
|
||||||
CharType* Data;
|
|
||||||
size_t Size;
|
|
||||||
};
|
|
||||||
#define StringBufferParam(str) { (str), sizeof(str) }
|
|
||||||
|
|
||||||
using FunctionPtr = auto (*)(void) -> void;
|
using FunctionPtr = auto (*)(void) -> void;
|
||||||
|
|
||||||
// Limits
|
// Limits
|
||||||
|
|||||||
154
Juliet/include/Core/Common/String.h
Normal file
154
Juliet/include/Core/Common/String.h
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/CoreUtils.h>
|
||||||
|
#include <Core/Memory/Utils.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
#define ConstString(str) { const_cast<char*>((str)), sizeof(str) - 1 }
|
||||||
|
#define CStr(str) ((str).Data)
|
||||||
|
#define InplaceString(name, size) \
|
||||||
|
char name##_[size]; \
|
||||||
|
MemSet(name##_, 0, sizeof(uint32)); \
|
||||||
|
String name = { name##_, 0 }
|
||||||
|
|
||||||
|
// Everything is Little Endian
|
||||||
|
enum class StringEncoding : uint8
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
ASCII,
|
||||||
|
LATIN1,
|
||||||
|
UTF8,
|
||||||
|
UTF16,
|
||||||
|
UTF32,
|
||||||
|
UCS2,
|
||||||
|
UCS4,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Represents a UTF-8 String.
|
||||||
|
// Not null terminated.
|
||||||
|
struct String
|
||||||
|
{
|
||||||
|
char* Data;
|
||||||
|
size_t Size;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline size_t StringLength(String str)
|
||||||
|
{
|
||||||
|
return str.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t StringLength(const char* str)
|
||||||
|
{
|
||||||
|
size_t length = 0;
|
||||||
|
if (str)
|
||||||
|
{
|
||||||
|
while (char ch = *str)
|
||||||
|
{
|
||||||
|
if ((ch & 0xC0) != 0x80)
|
||||||
|
{
|
||||||
|
++length;
|
||||||
|
}
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool StringIsValid(String str)
|
||||||
|
{
|
||||||
|
return str.Size > 0 && str.Data != nullptr && *str.Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline String WrapString(const char* str)
|
||||||
|
{
|
||||||
|
String result = {};
|
||||||
|
result.Data = const_cast<char*>(str);
|
||||||
|
result.Size = StringLength(str);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline String FindChar(String str, char c)
|
||||||
|
{
|
||||||
|
String result = str;
|
||||||
|
while (result.Size)
|
||||||
|
{
|
||||||
|
if (*result.Data != c)
|
||||||
|
{
|
||||||
|
++result.Data;
|
||||||
|
--result.Size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ContainsChar(String str, char c)
|
||||||
|
{
|
||||||
|
return StringIsValid(FindChar(str, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return:
|
||||||
|
// - < 0 if str1 < str2
|
||||||
|
// - = 0 : Both strings are equals
|
||||||
|
// - > 0 if str1 > str2
|
||||||
|
inline int32 StringCompare(String str1, String str2)
|
||||||
|
{
|
||||||
|
size_t len1 = StringLength(str1);
|
||||||
|
size_t len2 = StringLength(str2);
|
||||||
|
size_t minLen = Min(len1, len2);
|
||||||
|
int32 result = MemCompare(CStr(str1), CStr(str2), minLen);
|
||||||
|
if (result == 0)
|
||||||
|
{
|
||||||
|
if (len1 > len2)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (len1 < len2)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case insensitive compare. Supports ASCII only
|
||||||
|
// TODO: Support UNICODE
|
||||||
|
extern JULIET_API int8 StringCompareCaseInsensitive(String str1, String str2);
|
||||||
|
|
||||||
|
// Do not allocate anything, you must allocate your out buffer yourself
|
||||||
|
// TODO: Version taking arena that can allocate
|
||||||
|
// Do not take String type because we dont know the string encoding we are going from/to
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
} // namespace Juliet
|
||||||
|
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
namespace Juliet::UnitTest
|
||||||
|
{
|
||||||
|
inline void TestFindChar()
|
||||||
|
{
|
||||||
|
String s1 = ConstString("");
|
||||||
|
String s2 = ConstString("abcdefabcdef");
|
||||||
|
String s3 = ConstString("11111111111111111111");
|
||||||
|
|
||||||
|
Assert(FindChar(s1, 'x').Data == nullptr);
|
||||||
|
Assert(FindChar(s2, 'y').Data == nullptr);
|
||||||
|
Assert(FindChar(s2, 'a').Data - s2.Data == 0);
|
||||||
|
Assert(FindChar(s2, 'd').Data - s2.Data == 3);
|
||||||
|
Assert(FindChar(s2, 'f').Data - s2.Data == 5);
|
||||||
|
Assert(FindChar(s3, '1').Data - s3.Data == 0);
|
||||||
|
}
|
||||||
|
} // namespace Juliet::UnitTest
|
||||||
|
#endif
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
// Returns the path to the application directory
|
// Returns the path to the application directory
|
||||||
extern JULIET_API char * GetBasePath();
|
extern JULIET_API String GetBasePath();
|
||||||
}
|
} // namespace Juliet
|
||||||
|
|||||||
12
Juliet/include/Core/HAL/IO/IOStream.h
Normal file
12
Juliet/include/Core/HAL/IO/IOStream.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/String.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
// Opaque type
|
||||||
|
struct IOStream;
|
||||||
|
|
||||||
|
extern JULIET_API IOStream* IOFromFile(String filename, String mode);
|
||||||
|
} // namespace Juliet
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
// Fwd Declare
|
// Fwd Declare
|
||||||
@@ -7,9 +9,9 @@ namespace Juliet
|
|||||||
|
|
||||||
struct HotReloadCode
|
struct HotReloadCode
|
||||||
{
|
{
|
||||||
StringBuffer<char> DLLFullPath;
|
String DLLFullPath;
|
||||||
StringBuffer<char> LockFullPath;
|
String LockFullPath;
|
||||||
StringBuffer<const char> TransientDLLName;
|
String TransientDLLName;
|
||||||
|
|
||||||
uint64 LastWriteTime;
|
uint64 LastWriteTime;
|
||||||
|
|
||||||
@@ -24,8 +26,8 @@ namespace Juliet
|
|||||||
bool IsValid : 1;
|
bool IsValid : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JULIET_API void InitHotReloadCode(HotReloadCode& code, StringBuffer<const char> dllName,
|
extern JULIET_API void InitHotReloadCode(HotReloadCode& code, String dllName,
|
||||||
StringBuffer<const char> transientDllName, StringBuffer<const char> lockFilename);
|
String transientDllName, String lockFilename);
|
||||||
extern JULIET_API void ShutdownHotReloadCode(HotReloadCode& code);
|
extern JULIET_API void ShutdownHotReloadCode(HotReloadCode& code);
|
||||||
|
|
||||||
extern JULIET_API void LoadCode(HotReloadCode& code);
|
extern JULIET_API void LoadCode(HotReloadCode& code);
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/CoreTypes.h>
|
||||||
|
|
||||||
#define ArraySize(array) (sizeof(array) / sizeof(array[0]))
|
#define ArraySize(array) (sizeof(array) / sizeof(array[0]))
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
inline int32 MemCompare(const void* leftValue, const void* rightValue, size_t size)
|
||||||
|
{
|
||||||
|
auto left = static_cast<const unsigned char*>(leftValue);
|
||||||
|
auto right = static_cast<const unsigned char*>(rightValue);
|
||||||
|
while (size && *left == *right)
|
||||||
|
{
|
||||||
|
++left;
|
||||||
|
++right;
|
||||||
|
}
|
||||||
|
return size ? *left - *right : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MemSet memset
|
||||||
|
} // namespace Juliet
|
||||||
|
|||||||
351
Juliet/src/Core/Common/String.cpp
Normal file
351
Juliet/src/Core/Common/String.cpp
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
#include <pch.h>
|
||||||
|
|
||||||
|
#include <Core/Common/String.h>
|
||||||
|
#include <Core/Memory/Utils.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr char kUnknown_ASCII = '?';
|
||||||
|
constexpr int32 kUnknown_UNICODE = 0xFFFD;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
String Name;
|
||||||
|
StringEncoding Format;
|
||||||
|
} Encodings[] = {
|
||||||
|
/* *INDENT-OFF* */ // clang-format off
|
||||||
|
{ ConstString("ASCII"), StringEncoding::ASCII },
|
||||||
|
{ ConstString("US-ASCII"), StringEncoding::ASCII },
|
||||||
|
{ ConstString("8859-1"), StringEncoding::LATIN1 },
|
||||||
|
{ ConstString("ISO-8859-1"), StringEncoding::LATIN1 },
|
||||||
|
#if defined(JULIET_WIN32)
|
||||||
|
{ ConstString("WCHAR_T"), StringEncoding::UTF16 },
|
||||||
|
#else
|
||||||
|
{ ConstString("WCHAR_T"), StringEncoding::UCS4 },
|
||||||
|
#endif
|
||||||
|
{ ConstString("UTF8"), StringEncoding::UTF8 },
|
||||||
|
{ ConstString("UTF-8"), StringEncoding::UTF8 },
|
||||||
|
{ ConstString("UTF16"), StringEncoding::UTF16 },
|
||||||
|
{ ConstString("UTF-16"), StringEncoding::UTF16 },
|
||||||
|
{ ConstString("UTF32"), StringEncoding::UTF32 },
|
||||||
|
{ ConstString("UTF-32"), StringEncoding::UTF32 },
|
||||||
|
{ ConstString("UCS2"), StringEncoding::UCS2 },
|
||||||
|
{ ConstString("UCS-2"), StringEncoding::UCS2 },
|
||||||
|
{ ConstString("UCS-2-INTERNAL"), StringEncoding::UCS2 },
|
||||||
|
{ ConstString("UCS4"), StringEncoding::UCS4 },
|
||||||
|
{ ConstString("UCS-4"), StringEncoding::UCS4 },
|
||||||
|
{ ConstString("UCS-4-INTERNAL"), StringEncoding::UCS4 },
|
||||||
|
/* *INDENT-ON* */ // clang-format on
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the number of codepoint case folded (lowercase equivalent in the language)
|
||||||
|
// Takes an UTF-8 codepoint (uint32) and codefold it to up to 3 uint32
|
||||||
|
// TODO Supports more than low ASCI :)
|
||||||
|
int8 CaseFoldUnicode(uint32 from, uint32* to)
|
||||||
|
{
|
||||||
|
if (from < 128)
|
||||||
|
{
|
||||||
|
// low-ASCII, easy!
|
||||||
|
if ((from >= 'A') && (from <= 'Z'))
|
||||||
|
{
|
||||||
|
*to = 'a' + (from - 'A');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*to = from;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Step(String& inStr, size_t byteToStep)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
|
||||||
|
int8 StringCompareCaseInsensitive(String str1, String str2)
|
||||||
|
{
|
||||||
|
// TODO: Support UTF8. For now ASCII only.
|
||||||
|
uint32 left = 0;
|
||||||
|
uint32 right = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
uint32 leftFolded[3];
|
||||||
|
int8 num_folded = CaseFoldUnicode(StepUTF8(str1, 4), 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);
|
||||||
|
Assert(num_folded == 1); // Only one uint32 codepoint supported for now (low ascii)
|
||||||
|
right = rightFolded[0];
|
||||||
|
}
|
||||||
|
if (left < right)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (left > right)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (left == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConvertString(StringEncoding from, StringEncoding to, const char* src, size_t srcLen, char*& dst, size_t& dstLen, size_t dstCapacity)
|
||||||
|
{
|
||||||
|
Assert(src && *src);
|
||||||
|
|
||||||
|
const char* srcStr = src;
|
||||||
|
char* dstStr = dst;
|
||||||
|
|
||||||
|
uint32 character = 0;
|
||||||
|
while (srcLen > 0)
|
||||||
|
{
|
||||||
|
// Decode in character
|
||||||
|
switch (from)
|
||||||
|
{
|
||||||
|
case StringEncoding::UTF8: // Uses RFC 3629
|
||||||
|
{
|
||||||
|
auto p = reinterpret_cast<const uint8*>(srcStr);
|
||||||
|
size_t left = 0;
|
||||||
|
bool overlong = false;
|
||||||
|
if (p[0] >= 0xF0)
|
||||||
|
{
|
||||||
|
if ((p[0] & 0xF8) != 0xF0)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p[0] == 0xF0 && srcLen > 1 && (p[1] & 0xF0) == 0x80)
|
||||||
|
{
|
||||||
|
overlong = true;
|
||||||
|
}
|
||||||
|
character = static_cast<uint32>(p[0] & 0x07);
|
||||||
|
left = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p[0] >= 0xE0)
|
||||||
|
{
|
||||||
|
if ((p[0] & 0xF0) != 0xE0)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p[0] == 0xE0 && srcLen > 1 && (p[1] & 0xE0) == 0x80)
|
||||||
|
{
|
||||||
|
overlong = true;
|
||||||
|
}
|
||||||
|
character = static_cast<uint32>(p[0] & 0x0F);
|
||||||
|
left = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p[0] >= 0xC0)
|
||||||
|
{
|
||||||
|
if ((p[0] & 0xE0) != 0xC0)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((p[0] & 0xDE) == 0xC0)
|
||||||
|
{
|
||||||
|
overlong = true;
|
||||||
|
}
|
||||||
|
character = static_cast<uint32>(p[0] & 0x1F);
|
||||||
|
left = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p[0] & 0x80)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
character = static_cast<uint32>(p[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++srcStr;
|
||||||
|
--srcLen;
|
||||||
|
if (srcLen < left)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Failed to convert string. Incomplete input sequence");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (left--)
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
if ((p[0] & 0xC0) != 0x80)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
character <<= 6;
|
||||||
|
character |= (p[0] & 0x3F);
|
||||||
|
++srcStr;
|
||||||
|
--srcLen;
|
||||||
|
}
|
||||||
|
if (overlong)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
if ((character >= 0xD800 && character <= 0xDFFF) || (character == 0xFFFE || character == 0xFFFF) ||
|
||||||
|
character > 0x10FFFF)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StringEncoding::Unknown: Assert(false && "ConvertString: Invalid Source Format: Unknown"); break;
|
||||||
|
case StringEncoding::ASCII:
|
||||||
|
case StringEncoding::LATIN1:
|
||||||
|
case StringEncoding::UTF16:
|
||||||
|
case StringEncoding::UTF32:
|
||||||
|
case StringEncoding::UCS2:
|
||||||
|
case StringEncoding::UCS4: Assert(false && "ConvertString: Unsupported Source Format"); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode out character
|
||||||
|
switch (to)
|
||||||
|
{
|
||||||
|
case StringEncoding::UTF16: // RFC 2781
|
||||||
|
{
|
||||||
|
auto p = reinterpret_cast<uint8*>(dstStr);
|
||||||
|
if (character > 0x10FFFF)
|
||||||
|
{
|
||||||
|
character = kUnknown_UNICODE;
|
||||||
|
}
|
||||||
|
if (character < 0x10000)
|
||||||
|
{
|
||||||
|
if (dstCapacity < 2)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Destination buffer too short to fit UTF16");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
p[1] = static_cast<uint8>(character >> 8);
|
||||||
|
p[0] = static_cast<uint8>(character);
|
||||||
|
|
||||||
|
dstStr += 2;
|
||||||
|
dstLen += 1;
|
||||||
|
dstCapacity -= 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (dstCapacity < 4)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Core, "ConvertString: Destination buffer too short to fit UTF16");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
character = character - 0x10000;
|
||||||
|
uint16 word1 = 0xD800 | static_cast<uint16>((character >> 10) & 0x3FF);
|
||||||
|
uint16 word2 = 0xDC00 | static_cast<uint16>(character & 0x3FF);
|
||||||
|
p[1] = static_cast<uint8>(word1 >> 8);
|
||||||
|
p[0] = static_cast<uint8>(word1);
|
||||||
|
p[3] = static_cast<uint8>(word2 >> 8);
|
||||||
|
p[2] = static_cast<uint8>(word2);
|
||||||
|
|
||||||
|
dstStr += 4;
|
||||||
|
dstLen += 1;
|
||||||
|
dstCapacity -= 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StringEncoding::Unknown: Assert(false && "ConvertString: Invalid Source Format: Unknown"); break;
|
||||||
|
case StringEncoding::ASCII:
|
||||||
|
case StringEncoding::LATIN1:
|
||||||
|
case StringEncoding::UTF8:
|
||||||
|
case StringEncoding::UTF32:
|
||||||
|
case StringEncoding::UCS2:
|
||||||
|
case StringEncoding::UCS4: Assert(false && "ConvertString: Unsupported Destination Format"); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConvertString(String from, String to, const char* src, size_t srcSize, char*& dst, size_t& dstSize, size_t dstCapacity)
|
||||||
|
{
|
||||||
|
Assert(StringIsValid(from));
|
||||||
|
Assert(StringIsValid(to));
|
||||||
|
|
||||||
|
// First find the encoding of the strings
|
||||||
|
auto sourceFormat = StringEncoding::Unknown;
|
||||||
|
auto destFormat = StringEncoding::Unknown;
|
||||||
|
for (auto& encoding : Encodings)
|
||||||
|
{
|
||||||
|
if (StringCompareCaseInsensitive(from, encoding.Name) == 0)
|
||||||
|
{
|
||||||
|
sourceFormat = encoding.Format;
|
||||||
|
if (destFormat != StringEncoding::Unknown)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StringCompareCaseInsensitive(to, encoding.Name) == 0)
|
||||||
|
{
|
||||||
|
destFormat = encoding.Format;
|
||||||
|
if (sourceFormat != StringEncoding::Unknown)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceFormat == StringEncoding::Unknown || destFormat == StringEncoding::Unknown)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConvertString(sourceFormat, destFormat, src, srcSize, dst, dstSize, dstCapacity);
|
||||||
|
}
|
||||||
|
} // namespace Juliet
|
||||||
@@ -134,10 +134,10 @@ namespace Juliet::Win32
|
|||||||
{
|
{
|
||||||
uint8 peekedMessageCount = 0;
|
uint8 peekedMessageCount = 0;
|
||||||
MSG message = {};
|
MSG message = {};
|
||||||
while (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE))
|
while (PeekMessageA(&message, nullptr, 0, 0, PM_REMOVE))
|
||||||
{
|
{
|
||||||
TranslateMessage(&message);
|
TranslateMessage(&message);
|
||||||
DispatchMessage(&message);
|
DispatchMessageA(&message);
|
||||||
|
|
||||||
// Since we peek at all messages of the program, it's possible that it stall here so we limit the number of peeked messages to an arbitrary limit
|
// Since we peek at all messages of the program, it's possible that it stall here so we limit the number of peeked messages to an arbitrary limit
|
||||||
if (++peekedMessageCount > kPeekMessageLimit)
|
if (++peekedMessageCount > kPeekMessageLimit)
|
||||||
@@ -155,7 +155,7 @@ namespace Juliet::Win32
|
|||||||
auto* windowState = GetWindowStateFromHandle(handle);
|
auto* windowState = GetWindowStateFromHandle(handle);
|
||||||
if (!windowState)
|
if (!windowState)
|
||||||
{
|
{
|
||||||
return CallWindowProc(DefWindowProc, handle, message, wParam, lParam);
|
return CallWindowProcA(DefWindowProcA, handle, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (message)
|
switch (message)
|
||||||
@@ -267,6 +267,6 @@ namespace Juliet::Win32
|
|||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CallWindowProc(DefWindowProc, handle, message, wParam, lParam);
|
return CallWindowProcA(DefWindowProcA, handle, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
} // namespace Juliet::Win32
|
} // namespace Juliet::Win32
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ namespace Juliet::Win32
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
constexpr auto WindowClassName = L"JulietWindowClass";
|
constexpr auto WindowClassName = "JulietWindowClass";
|
||||||
constexpr LPCWSTR WindowClassPtr = WindowClassName;
|
constexpr LPCSTR WindowClassPtr = WindowClassName;
|
||||||
|
|
||||||
bool SetupWindowState(NonNullPtr<DisplayDevice> self, NonNullPtr<Window> window, HWND handle)
|
bool SetupWindowState(NonNullPtr<DisplayDevice> self, NonNullPtr<Window> window, HWND handle)
|
||||||
{
|
{
|
||||||
@@ -46,7 +46,7 @@ namespace Juliet::Win32
|
|||||||
HINSTANCE instance = GetModuleHandle(nullptr);
|
HINSTANCE instance = GetModuleHandle(nullptr);
|
||||||
|
|
||||||
// TODO : Put outside, we should not create a new class for each new window
|
// TODO : Put outside, we should not create a new class for each new window
|
||||||
WNDCLASSEX WindowClass = {};
|
WNDCLASSEXA WindowClass = {};
|
||||||
WindowClass.cbSize = sizeof(WNDCLASSEX);
|
WindowClass.cbSize = sizeof(WNDCLASSEX);
|
||||||
WindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
WindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||||
WindowClass.lpfnWndProc = Win32MainWindowCallback;
|
WindowClass.lpfnWndProc = Win32MainWindowCallback;
|
||||||
@@ -54,7 +54,7 @@ namespace Juliet::Win32
|
|||||||
WindowClass.hCursor = LoadCursor(0, IDC_ARROW);
|
WindowClass.hCursor = LoadCursor(0, IDC_ARROW);
|
||||||
WindowClass.hbrBackground = static_cast<HBRUSH>(GetStockObject(LTGRAY_BRUSH));
|
WindowClass.hbrBackground = static_cast<HBRUSH>(GetStockObject(LTGRAY_BRUSH));
|
||||||
WindowClass.lpszClassName = WindowClassName;
|
WindowClass.lpszClassName = WindowClassName;
|
||||||
if (!RegisterClassEx(&WindowClass))
|
if (!RegisterClassExA(&WindowClass))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ namespace Juliet::Win32
|
|||||||
|
|
||||||
int x = CW_USEDEFAULT, y = CW_USEDEFAULT;
|
int x = CW_USEDEFAULT, y = CW_USEDEFAULT;
|
||||||
const int w = window->Width, h = window->Height;
|
const int w = window->Width, h = window->Height;
|
||||||
HWND handle = CreateWindowEx(styleEx, WindowClassPtr, L"JULIET TODO PASS TITLE", style, x, y, w, h, nullptr,
|
HWND handle = CreateWindowExA(styleEx, WindowClassPtr, "JULIET TODO PASS TITLE", style, x, y, w, h, nullptr,
|
||||||
nullptr, instance, nullptr);
|
nullptr, instance, nullptr);
|
||||||
|
|
||||||
PumpEvents(self);
|
PumpEvents(self);
|
||||||
@@ -97,69 +97,4 @@ namespace Juliet::Win32
|
|||||||
auto& win32State = reinterpret_cast<Window32State&>(*window->State);
|
auto& win32State = reinterpret_cast<Window32State&>(*window->State);
|
||||||
::ShowWindow(win32State.Handle, SW_HIDE);
|
::ShowWindow(win32State.Handle, SW_HIDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
LRESULT CALLBACK Win32MainWindowCallback(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreateOSWindow(WindowState& state, uint16 width, uint16 height)
|
|
||||||
{
|
|
||||||
auto& win32State = reinterpret_cast<Window32State&>(state);
|
|
||||||
|
|
||||||
HINSTANCE Instance = GetModuleHandle(0);
|
|
||||||
|
|
||||||
WNDCLASSA WindowClass = {};
|
|
||||||
WindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
|
||||||
WindowClass.lpfnWndProc = Win32MainWindowCallback;
|
|
||||||
WindowClass.hInstance = Instance;
|
|
||||||
WindowClass.hCursor = LoadCursor(0, IDC_ARROW);
|
|
||||||
WindowClass.hbrBackground = static_cast<HBRUSH>(GetStockObject(LTGRAY_BRUSH));
|
|
||||||
WindowClass.lpszClassName = WindowClassName;
|
|
||||||
|
|
||||||
if (RegisterClassA(&WindowClass))
|
|
||||||
{
|
|
||||||
HWND handle = CreateWindowExA(0, WindowClass.lpszClassName, "Juliet", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
|
|
||||||
CW_USEDEFAULT, width, height, 0, 0, Instance, 0);
|
|
||||||
if (handle)
|
|
||||||
{
|
|
||||||
win32State.Handle = handle;
|
|
||||||
SetWindowLongPtr(win32State.Handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(&win32State));
|
|
||||||
ShowWindow(handle, SW_SHOW);
|
|
||||||
win32State.IsOpen = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Assert(false);
|
|
||||||
// Win32ErrorMessage(PlatformError_Fatal,
|
|
||||||
// "Unable to open game window.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Assert(false);
|
|
||||||
// Win32ErrorMessage(PlatformError_Fatal,
|
|
||||||
// "Unable to register game window handle.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DestroyOSWindow(WindowState& state)
|
|
||||||
{
|
|
||||||
auto& win32State = reinterpret_cast<Window32State&>(state);
|
|
||||||
::DestroyWindow(win32State.Handle);
|
|
||||||
UnregisterClassA(WindowClassName, ::GetModuleHandle(nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateOSWindowState(WindowState& state)
|
|
||||||
{
|
|
||||||
auto& win32State = reinterpret_cast<Window32State&>(state);
|
|
||||||
MSG msg = {};
|
|
||||||
while (::PeekMessage(&msg, win32State.Handle, 0, 0, PM_REMOVE))
|
|
||||||
{
|
|
||||||
::TranslateMessage(&msg);
|
|
||||||
::DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
} // namespace Juliet::Win32
|
} // namespace Juliet::Win32
|
||||||
|
|||||||
@@ -5,38 +5,6 @@
|
|||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
namespace
|
|
||||||
{
|
|
||||||
// TODO : Move into string file
|
|
||||||
// Use portable code + pass the memory array into parameter and not use new
|
|
||||||
// This is from http://www.rohitab.com/discuss/topic/41257-char-to-lpcwstr/
|
|
||||||
static wchar_t* UTF8ToWideChar(const char* utf8)
|
|
||||||
{
|
|
||||||
wchar_t* w;
|
|
||||||
|
|
||||||
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, 0, 0);
|
|
||||||
if (len <= 0)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
w = new wchar_t[len];
|
|
||||||
|
|
||||||
if (!w)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MultiByteToWideChar(CP_UTF8, 0, utf8, -1, w, len) <= 0)
|
|
||||||
{
|
|
||||||
delete[] w;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
DynamicLibrary* LoadDynamicLibrary(const char* filename)
|
DynamicLibrary* LoadDynamicLibrary(const char* filename)
|
||||||
{
|
{
|
||||||
if (!filename)
|
if (!filename)
|
||||||
@@ -45,9 +13,7 @@ namespace Juliet
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPWSTR wstr = UTF8ToWideChar(filename);
|
HMODULE handle = LoadLibraryA(filename);
|
||||||
HMODULE handle = LoadLibraryW(wstr);
|
|
||||||
delete[] wstr;
|
|
||||||
|
|
||||||
// Generate an error message if all loads failed
|
// Generate an error message if all loads failed
|
||||||
if (!handle)
|
if (!handle)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <pch.h>
|
#include <pch.h>
|
||||||
|
|
||||||
|
#include <Core/Common/String.h>
|
||||||
#include <Core/HAL/Filesystem/Filesystem.h>
|
#include <Core/HAL/Filesystem/Filesystem.h>
|
||||||
#include <Core/HAL/Filesystem/Filesystem_Platform.h>
|
#include <Core/HAL/Filesystem/Filesystem_Platform.h>
|
||||||
#include <Core/HAL/Filesystem/Filesystem_Private.h>
|
#include <Core/HAL/Filesystem/Filesystem_Private.h>
|
||||||
@@ -9,11 +10,12 @@ namespace Juliet
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
char* CachedBasePath = nullptr;
|
String CachedBasePath = {};
|
||||||
}
|
}
|
||||||
char* GetBasePath()
|
|
||||||
|
String GetBasePath()
|
||||||
{
|
{
|
||||||
if (CachedBasePath == nullptr)
|
if (!StringIsValid(CachedBasePath))
|
||||||
{
|
{
|
||||||
CachedBasePath = Platform::GetBasePath();
|
CachedBasePath = Platform::GetBasePath();
|
||||||
}
|
}
|
||||||
@@ -24,9 +26,10 @@ namespace Juliet
|
|||||||
|
|
||||||
void ShutdownFilesystem()
|
void ShutdownFilesystem()
|
||||||
{
|
{
|
||||||
if (CachedBasePath != nullptr)
|
if (StringIsValid(CachedBasePath))
|
||||||
{
|
{
|
||||||
SafeFree(CachedBasePath);
|
CachedBasePath.Size = 0;
|
||||||
|
SafeFree(CachedBasePath.Data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
namespace Juliet::Platform
|
namespace Juliet::Platform
|
||||||
{
|
{
|
||||||
extern char* GetBasePath();
|
extern String GetBasePath();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,62 +1,33 @@
|
|||||||
#include <pch.h>
|
#include <pch.h>
|
||||||
|
|
||||||
|
#include <Core/Common/String.h>
|
||||||
#include <Core/HAL/Filesystem/Filesystem_Platform.h>
|
#include <Core/HAL/Filesystem/Filesystem_Platform.h>
|
||||||
#include <Core/HAL/Win32.h>
|
#include <Core/HAL/Win32.h>
|
||||||
#include <Core/Memory/Allocator.h>
|
#include <Core/Memory/Allocator.h>
|
||||||
|
|
||||||
namespace Juliet::Platform
|
namespace Juliet::Platform
|
||||||
{
|
{
|
||||||
namespace
|
String GetBasePath()
|
||||||
{
|
|
||||||
// TODO : Move into string file
|
|
||||||
// Use portable code + pass the memory array into parameter and not use new
|
|
||||||
// From: https://stackoverflow.com/questions/215963/how-do-you-properly-use-widechartomultibyte
|
|
||||||
char* WideCharToUTF8(wchar_t* wcharStr)
|
|
||||||
{
|
|
||||||
char* result = nullptr;
|
|
||||||
size_t length = WideCharToMultiByte(CP_UTF8, 0, wcharStr, -1, nullptr, 0, nullptr, nullptr);
|
|
||||||
if (length <= 0)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = new char[length];
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WideCharToMultiByte(CP_UTF8, 0, wcharStr, -1, result, length, nullptr, nullptr) <= 0)
|
|
||||||
{
|
|
||||||
delete[] result;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
char* GetBasePath()
|
|
||||||
{
|
{
|
||||||
// Allocate a buffer that could fit the module size.
|
// Allocate a buffer that could fit the module size.
|
||||||
// Max Path is a good start but could be bigger if the path include long path prefix
|
// Max Path is a good start but could be bigger if the path include long path prefix
|
||||||
StringBuffer<WCHAR> buffer{ .Data = nullptr, .Size = MAX_PATH };
|
size_t bufferSize=MAX_PATH;
|
||||||
buffer.Data = static_cast<WCHAR*>(Calloc(MAX_PATH, sizeof(WCHAR)));
|
auto buffer = static_cast<char*>(Calloc(MAX_PATH, sizeof(char)));
|
||||||
if (buffer.Data == nullptr)
|
if (buffer == nullptr)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t moduleFilenameLength = 0;
|
size_t moduleFilenameLength = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
moduleFilenameLength = GetModuleFileNameW(nullptr, buffer.Data, static_cast<uint32>(buffer.Size));
|
moduleFilenameLength = GetModuleFileNameA(nullptr, buffer, static_cast<uint32>(bufferSize));
|
||||||
|
|
||||||
// If the module filename length is bigger than the buffer size, we need to reallocate a bigger buffer
|
// If the module filename length is bigger than the buffer size, we need to reallocate a bigger buffer
|
||||||
if (moduleFilenameLength >= buffer.Size - 1)
|
if (moduleFilenameLength >= bufferSize - 1)
|
||||||
{
|
{
|
||||||
buffer.Size *= 2;
|
bufferSize *= 2;
|
||||||
buffer.Data = static_cast<WCHAR*>(Realloc(buffer.Data, buffer.Size * sizeof(WCHAR)));
|
buffer = static_cast<char*>(Realloc(buffer, bufferSize * sizeof(char)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -66,25 +37,23 @@ namespace Juliet::Platform
|
|||||||
|
|
||||||
if (moduleFilenameLength == 0)
|
if (moduleFilenameLength == 0)
|
||||||
{
|
{
|
||||||
SafeFree(buffer.Data);
|
SafeFree(buffer);
|
||||||
Log(LogLevel::Error, LogCategory::Core, "Filesystem: Cannot locate executable path");
|
Log(LogLevel::Error, LogCategory::Core, "Filesystem: Cannot locate executable path");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
for (idx = moduleFilenameLength - 1; idx > 0; --idx)
|
for (idx = moduleFilenameLength - 1; idx > 0; --idx)
|
||||||
{
|
{
|
||||||
if (buffer.Data[idx] == '\\')
|
if (buffer[idx] == '\\')
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(idx > 0 && "Path is not absolute!");
|
Assert(idx > 0 && "Path is not absolute!");
|
||||||
buffer.Data[idx + 1] = '\0'; // Chop chop
|
buffer[idx + 1] = '\0'; // Chop chop
|
||||||
|
|
||||||
// TODO: Add utils to Convert to/from UTF8W
|
return WrapString(buffer);
|
||||||
char* basePath = WideCharToUTF8(buffer.Data);
|
|
||||||
SafeFree(buffer.Data);
|
|
||||||
return basePath;
|
|
||||||
}
|
}
|
||||||
} // namespace Juliet::Platform
|
} // namespace Juliet::Platform
|
||||||
|
|||||||
24
Juliet/src/Core/HAL/IO/IOStream.cpp
Normal file
24
Juliet/src/Core/HAL/IO/IOStream.cpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include <pch.h>
|
||||||
|
|
||||||
|
#include <Core/Common/String.h>
|
||||||
|
#include <Core/HAL/IO/IOStream.h>
|
||||||
|
#include <Core/HAL/IO/IOStream_Private.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
IOStream* IOFromFile(String filename, String mode)
|
||||||
|
{
|
||||||
|
if (!StringIsValid(filename))
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Core, "Trying to open IOStream on invalid filename");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (!StringIsValid(mode))
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Core, "Trying to open IOStream with invalid mode");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Internal::IOFromFile(filename, mode);
|
||||||
|
}
|
||||||
|
} // namespace Juliet
|
||||||
12
Juliet/src/Core/HAL/IO/IOStream_Private.h
Normal file
12
Juliet/src/Core/HAL/IO/IOStream_Private.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/String.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
struct IOStream;
|
||||||
|
}
|
||||||
|
namespace Juliet::Internal
|
||||||
|
{
|
||||||
|
extern JULIET_API IOStream* IOFromFile(String filename, String mode);
|
||||||
|
}
|
||||||
59
Juliet/src/Core/HAL/IO/Win32/Win32IOStream.cpp
Normal file
59
Juliet/src/Core/HAL/IO/Win32/Win32IOStream.cpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include <pch.h>
|
||||||
|
|
||||||
|
#include <Core/Common/String.h>
|
||||||
|
#include <Core/HAL/IO/IOStream.h>
|
||||||
|
#include <Core/HAL/Win32.h>
|
||||||
|
|
||||||
|
namespace Juliet::Internal
|
||||||
|
{
|
||||||
|
IOStream* IOFromFile(String filename, String mode)
|
||||||
|
{
|
||||||
|
// "r" = reading, file must exist
|
||||||
|
// "w" = writing, truncate existing, file may not exist
|
||||||
|
// "r+"= reading or writing, file must exist
|
||||||
|
// "a" = writing, append file may not exist
|
||||||
|
// "a+"= append + read, file may not exist
|
||||||
|
// "w+" = read, write, truncate. file may not exist
|
||||||
|
|
||||||
|
#if _DEBUG
|
||||||
|
// Making sure the mode is valid
|
||||||
|
String modeView = mode;
|
||||||
|
size_t modeLength = StringLength(modeView);
|
||||||
|
Assert(!ContainsChar(mode, 'b') && "Binary mode note supported");
|
||||||
|
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' && "Invalid Mode. First char is not r,w or a");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert(modeView.Data[1] == '+' && "Invalid Mode. Second char is not +");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DWORD openExisting = ContainsChar(mode, 'r') ? OPEN_EXISTING : 0;
|
||||||
|
DWORD createAlways = ContainsChar(mode, 'w') ? CREATE_ALWAYS : 0;
|
||||||
|
DWORD openAlways = ContainsChar(mode, 'a') ? OPEN_ALWAYS : 0;
|
||||||
|
|
||||||
|
bool hasPlus = ContainsChar(mode, '+');
|
||||||
|
DWORD canRead = openExisting || hasPlus ? GENERIC_READ : 0;
|
||||||
|
DWORD canWrite = createAlways || openAlways || hasPlus ? GENERIC_WRITE : 0;
|
||||||
|
|
||||||
|
if (!canRead && !canWrite)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Core, "IOFromFile: Invalid Mode (cannot read nor write)");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE hFile = CreateFileA(CStr(filename), (canWrite | canRead), (canWrite) ? 0 : FILE_SHARE_READ, nullptr,
|
||||||
|
(openExisting | createAlways | openAlways), FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
|
if (FAILED(hFile))
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Core, "IOFromFile: CreateFileW failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} // namespace Juliet::Internal
|
||||||
@@ -9,33 +9,32 @@
|
|||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
void InitHotReloadCode(HotReloadCode& code, StringBuffer<const char> dllName,
|
void InitHotReloadCode(HotReloadCode& code, String dllName, String transientDllName, String lockFilename)
|
||||||
StringBuffer<const char> transientDllName, StringBuffer<const char> lockFilename)
|
|
||||||
{
|
{
|
||||||
// Get the app base path and build the dll path from there.
|
// Get the app base path and build the dll path from there.
|
||||||
const char* basePath = GetBasePath();
|
String basePath = GetBasePath();
|
||||||
size_t basePathLength = strlen(basePath);
|
size_t basePathLength = StringLength(basePath);
|
||||||
|
|
||||||
// Assign Transient dll path
|
// Assign Transient dll path
|
||||||
code.TransientDLLName = transientDllName;
|
code.TransientDLLName = transientDllName;
|
||||||
|
|
||||||
// First allocate all the full path.
|
// First allocate all the full path.
|
||||||
// TODO: Add path composition into filesystem + string format + string builder
|
// TODO: Add path composition into filesystem + string format + string builder
|
||||||
const size_t dllFullPathLength = basePathLength + dllName.Size;
|
const size_t dllFullPathLength = basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings
|
||||||
code.DLLFullPath.Data = static_cast<char*>(Calloc(dllFullPathLength, sizeof(char)));
|
code.DLLFullPath.Data = static_cast<char*>(Calloc(dllFullPathLength, sizeof(char)));
|
||||||
int writtenSize = snprintf(code.DLLFullPath.Data, dllFullPathLength, "%s%s", basePath, dllName.Data);
|
int writtenSize = snprintf(CStr(code.DLLFullPath), dllFullPathLength, "%s%s", CStr(basePath), CStr(dllName));
|
||||||
if (writtenSize < static_cast<int>(dllFullPathLength) - 1)
|
if (writtenSize < static_cast<int>(dllFullPathLength) - 1)
|
||||||
{
|
{
|
||||||
SafeFree(code.DLLFullPath.Data);
|
SafeFree(code.DLLFullPath.Data);
|
||||||
Log(LogLevel::Error, LogCategory::Core, "Cannot create DLL Full Path");
|
Log(LogLevel::Error, LogCategory::Core, "Cannot create DLL Full Path");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
code.DLLFullPath.Size = writtenSize + 1;
|
code.DLLFullPath.Size = writtenSize;
|
||||||
|
|
||||||
// Lock filename path
|
// Lock filename path
|
||||||
const size_t lockPathLength = basePathLength + lockFilename.Size;
|
const size_t lockPathLength = basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings
|
||||||
code.LockFullPath.Data = static_cast<char*>(Calloc(lockPathLength, sizeof(char)));
|
code.LockFullPath.Data = static_cast<char*>(Calloc(lockPathLength, sizeof(char)));
|
||||||
writtenSize = snprintf(code.LockFullPath.Data, lockPathLength, "%s%s", basePath, lockFilename.Data);
|
writtenSize = snprintf(CStr(code.LockFullPath), lockPathLength, "%s%s", CStr(basePath), CStr(lockFilename));
|
||||||
if (writtenSize < static_cast<int>(lockPathLength) - 1)
|
if (writtenSize < static_cast<int>(lockPathLength) - 1)
|
||||||
{
|
{
|
||||||
code.LockFullPath.Size = 0;
|
code.LockFullPath.Size = 0;
|
||||||
@@ -43,7 +42,7 @@ namespace Juliet
|
|||||||
Log(LogLevel::Error, LogCategory::Core, "Cannot create lock file full path");
|
Log(LogLevel::Error, LogCategory::Core, "Cannot create lock file full path");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
code.LockFullPath.Size = writtenSize + 1;
|
code.LockFullPath.Size = writtenSize;
|
||||||
|
|
||||||
LoadCode(code);
|
LoadCode(code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Juliet
|
|||||||
|
|
||||||
constexpr size_t kMaxAttempts = 256;
|
constexpr size_t kMaxAttempts = 256;
|
||||||
constexpr size_t kMaxDLLID = 256;
|
constexpr size_t kMaxDLLID = 256;
|
||||||
constexpr size_t kTempDLLBufferSizeForID = 6; // ID numbers + \0
|
constexpr size_t kTempDLLBufferSizeForID = 5; // Max ID numbers
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void LoadCode(HotReloadCode& code)
|
void LoadCode(HotReloadCode& code)
|
||||||
@@ -48,20 +48,21 @@ namespace Juliet
|
|||||||
// We'll see for better later.
|
// We'll see for better later.
|
||||||
|
|
||||||
// Get the app base path and build the dll path from there.
|
// Get the app base path and build the dll path from there.
|
||||||
const char* basePath = GetBasePath();
|
String basePath = GetBasePath();
|
||||||
size_t basePathLength = strlen(basePath);
|
size_t basePathLength = StringLength(basePath);
|
||||||
|
|
||||||
const size_t tempDllMaxBufferSize = basePathLength + code.TransientDLLName.Size + kTempDLLBufferSizeForID;
|
const size_t tempDllMaxBufferSize =
|
||||||
|
basePathLength + StringLength(code.TransientDLLName) + /* _ */ 1 + kTempDLLBufferSizeForID + 1 /* \0 */;
|
||||||
auto tempDllPath = static_cast<char*>(Calloc(tempDllMaxBufferSize, sizeof(char)));
|
auto tempDllPath = static_cast<char*>(Calloc(tempDllMaxBufferSize, sizeof(char)));
|
||||||
for (uint32 attempt = 0; attempt < kMaxAttempts; ++attempt)
|
for (uint32 attempt = 0; attempt < kMaxAttempts; ++attempt)
|
||||||
{
|
{
|
||||||
// int to char
|
// int to char
|
||||||
char idToStr[kTempDLLBufferSizeForID];
|
char idToStr[kTempDLLBufferSizeForID + 1];
|
||||||
int idLength = snprintf(idToStr, sizeof(idToStr), "%u", code.UniqueID);
|
int idLength = snprintf(idToStr, sizeof(idToStr), "%u", code.UniqueID);
|
||||||
|
|
||||||
int writtenSize = snprintf(tempDllPath, tempDllMaxBufferSize, "%s%u_%s", basePath, code.UniqueID,
|
int writtenSize = snprintf(tempDllPath, tempDllMaxBufferSize, "%s%s_%s", CStr(basePath), idToStr,
|
||||||
code.TransientDLLName.Data);
|
CStr(code.TransientDLLName));
|
||||||
if (writtenSize < static_cast<int>(basePathLength + idLength + code.TransientDLLName.Size))
|
if (writtenSize < static_cast<int>(basePathLength + idLength + code.TransientDLLName.Size) - 1)
|
||||||
{
|
{
|
||||||
SafeFree(tempDllPath);
|
SafeFree(tempDllPath);
|
||||||
Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path");
|
Log(LogLevel::Error, LogCategory::Core, "Cannot create temp full path");
|
||||||
@@ -107,7 +108,10 @@ namespace Juliet
|
|||||||
void UnloadCode(HotReloadCode& code)
|
void UnloadCode(HotReloadCode& code)
|
||||||
{
|
{
|
||||||
code.IsValid = false;
|
code.IsValid = false;
|
||||||
|
if (code.Dll)
|
||||||
|
{
|
||||||
UnloadDynamicLibrary(code.Dll);
|
UnloadDynamicLibrary(code.Dll);
|
||||||
|
}
|
||||||
code.Dll = nullptr;
|
code.Dll = nullptr;
|
||||||
|
|
||||||
code.LastWriteTime = 0;
|
code.LastWriteTime = 0;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#include <D3D12Texture.h>
|
|
||||||
#include <pch.h>
|
#include <pch.h>
|
||||||
|
|
||||||
#include <core/Memory/Allocator.h>
|
#include <core/Memory/Allocator.h>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
Rename DX12 files to D3D12
|
- Rename DX12 files to D3D12
|
||||||
|
|
||||||
- Create Simple vector class to make the vector stuff a bit more easier than writing Capacity and Count
|
- Create Simple vector class to make the vector stuff a bit more easier than writing Capacity and Count
|
||||||
|
- Make a string struct instead of StringBuffer.
|
||||||
|
- Support wchar and char (template is ok) conversions, printf, compare, etc.
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <Core/Application/ApplicationManager.h>
|
#include <Core/Application/ApplicationManager.h>
|
||||||
#include <Core/HAL/Display/Display.h>
|
#include <Core/HAL/Display/Display.h>
|
||||||
#include <Core/HAL/DynLib/DynamicLibrary.h>
|
|
||||||
#include <Core/HAL/Event/SystemEvent.h>
|
#include <Core/HAL/Event/SystemEvent.h>
|
||||||
#include <Core/HAL/Filesystem/Filesystem.h>
|
#include <Core/HAL/Filesystem/Filesystem.h>
|
||||||
#include <Core/JulietInit.h>
|
#include <Core/JulietInit.h>
|
||||||
@@ -13,6 +12,7 @@
|
|||||||
#include <Graphics/RenderPass.h>
|
#include <Graphics/RenderPass.h>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <Core/Common/String.h>
|
||||||
#include <Core/Memory/Utils.h>
|
#include <Core/Memory/Utils.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ void JulietApplication::Init()
|
|||||||
{
|
{
|
||||||
Log(LogLevel::Message, LogCategory::Editor, "Initializing Juliet Application...");
|
Log(LogLevel::Message, LogCategory::Editor, "Initializing Juliet Application...");
|
||||||
|
|
||||||
Log(LogLevel::Message, LogCategory::Editor, "%s", GetBasePath());
|
Log(LogLevel::Message, LogCategory::Editor, "%s", CStr(GetBasePath()));
|
||||||
|
|
||||||
GraphicsConfig config;
|
GraphicsConfig config;
|
||||||
GraphicsDevice = CreateGraphicsDevice(config);
|
GraphicsDevice = CreateGraphicsDevice(config);
|
||||||
@@ -58,12 +58,11 @@ void JulietApplication::Init()
|
|||||||
if (Running)
|
if (Running)
|
||||||
{
|
{
|
||||||
AttachToWindow(GraphicsDevice, MainWindow);
|
AttachToWindow(GraphicsDevice, MainWindow);
|
||||||
// Game = LoadDynamicLibrary("Game.dll");
|
|
||||||
|
|
||||||
GameCode.Functions = reinterpret_cast<void**>(&Game);
|
GameCode.Functions = reinterpret_cast<void**>(&Game);
|
||||||
GameCode.FunctionCount = ArraySize(GameFunctionTable);
|
GameCode.FunctionCount = ArraySize(GameFunctionTable);
|
||||||
GameCode.FunctionNames = GameFunctionTable;
|
GameCode.FunctionNames = GameFunctionTable;
|
||||||
InitHotReloadCode(GameCode, StringBufferParam("Game.dll"), StringBufferParam("Game_Temp.dll"), StringBufferParam("lock.tmp"));
|
InitHotReloadCode(GameCode, ConstString("Game.dll"), ConstString("Game_Temp.dll"), ConstString("lock.tmp"));
|
||||||
if ((Running = GameCode.IsValid))
|
if ((Running = GameCode.IsValid))
|
||||||
{
|
{
|
||||||
Game.Init();
|
Game.Init();
|
||||||
|
|||||||
283
JulietShaderCompiler/DXCompiler.h
Normal file
283
JulietShaderCompiler/DXCompiler.h
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* Win32 Type Definitions */
|
||||||
|
|
||||||
|
using HRESULT = int;
|
||||||
|
using LPCVOID = const void*;
|
||||||
|
using SIZE_T = size_t;
|
||||||
|
using LPCSTR = const char*;
|
||||||
|
using UINT = unsigned int;
|
||||||
|
using ULONG = unsigned long;
|
||||||
|
using LPVOID = void*;
|
||||||
|
using REFIID = void*;
|
||||||
|
|
||||||
|
/* dxcompiler Type Definitions */
|
||||||
|
using BOOL = int;
|
||||||
|
using REFCLSID = void*;
|
||||||
|
using LPCWSTR = wchar_t*;
|
||||||
|
using IDxcBlobEncoding = void; /* hack, unused */
|
||||||
|
using IDxcBlobWide = void; /* hack, unused */
|
||||||
|
using IDxcIncludeHandler = void; /* hack, unused */
|
||||||
|
|
||||||
|
/* Unlike vkd3d-utils, libdxcompiler.so does not use msabi */
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#define __stdcall
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Compiler Interface, _technically_ unofficial but it's MS C++, come on */
|
||||||
|
using DXC_OUT_KIND = enum DXC_OUT_KIND {
|
||||||
|
DXC_OUT_NONE = 0,
|
||||||
|
DXC_OUT_OBJECT = 1,
|
||||||
|
DXC_OUT_ERRORS = 2,
|
||||||
|
DXC_OUT_PDB = 3,
|
||||||
|
DXC_OUT_SHADER_HASH = 4,
|
||||||
|
DXC_OUT_DISASSEMBLY = 5,
|
||||||
|
DXC_OUT_HLSL = 6,
|
||||||
|
DXC_OUT_TEXT = 7,
|
||||||
|
DXC_OUT_REFLECTION = 8,
|
||||||
|
DXC_OUT_ROOT_SIGNATURE = 9,
|
||||||
|
DXC_OUT_EXTRA_OUTPUTS = 10,
|
||||||
|
DXC_OUT_REMARKS = 11,
|
||||||
|
DXC_OUT_TIME_REPORT = 12,
|
||||||
|
DXC_OUT_TIME_TRACE = 13,
|
||||||
|
DXC_OUT_LAST = DXC_OUT_TIME_TRACE,
|
||||||
|
DXC_OUT_NUM_ENUMS,
|
||||||
|
// DXC_OUT_FORCE_DWORD = 0xFFFFFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DXC_CP_UTF8 65001
|
||||||
|
#define DXC_CP_UTF16 1200
|
||||||
|
#define DXC_CP_UTF32 12000
|
||||||
|
/* This is for binary, ANSI-text, or to tell the compiler to try autodetecting UTF using the BOM */
|
||||||
|
#define DXC_CP_ACP 0
|
||||||
|
|
||||||
|
using DxcBuffer = struct DxcBuffer
|
||||||
|
{
|
||||||
|
LPCVOID Ptr;
|
||||||
|
SIZE_T Size;
|
||||||
|
UINT Encoding;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */ // clang-format off
|
||||||
|
|
||||||
|
static uint8 IID_IDxcBlob[] = {
|
||||||
|
0x08, 0xFB, 0xA5, 0x8B,
|
||||||
|
0x95, 0x51,
|
||||||
|
0xE2, 0x40,
|
||||||
|
0xAC,
|
||||||
|
0x58,
|
||||||
|
0x0D,
|
||||||
|
0x98,
|
||||||
|
0x9C,
|
||||||
|
0x3A,
|
||||||
|
0x01,
|
||||||
|
0x02
|
||||||
|
};
|
||||||
|
using IDxcBlob = struct IDxcBlob;
|
||||||
|
using IDxcBlobVtbl = struct IDxcBlobVtbl
|
||||||
|
{
|
||||||
|
HRESULT(__stdcall *QueryInterface)(IDxcBlob *This, REFIID riid, void **ppvObject);
|
||||||
|
ULONG(__stdcall *AddRef)(IDxcBlob *This);
|
||||||
|
ULONG(__stdcall *Release)(IDxcBlob *This);
|
||||||
|
|
||||||
|
LPVOID(__stdcall *GetBufferPointer)(IDxcBlob *This);
|
||||||
|
SIZE_T(__stdcall *GetBufferSize)(IDxcBlob *This);
|
||||||
|
};
|
||||||
|
struct IDxcBlob
|
||||||
|
{
|
||||||
|
IDxcBlobVtbl *lpVtbl;
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8 IID_IDxcBlobUtf8[] = {
|
||||||
|
0xC9, 0x36, 0xA6, 0x3D,
|
||||||
|
0x71, 0xBA,
|
||||||
|
0x24, 0x40,
|
||||||
|
0xA3,
|
||||||
|
0x01,
|
||||||
|
0x30,
|
||||||
|
0xCB,
|
||||||
|
0xF1,
|
||||||
|
0x25,
|
||||||
|
0x30,
|
||||||
|
0x5B
|
||||||
|
};
|
||||||
|
using IDxcBlobUtf8 = struct IDxcBlobUtf8;
|
||||||
|
using IDxcBlobUtf8Vtbl = struct IDxcBlobUtf8Vtbl
|
||||||
|
{
|
||||||
|
HRESULT(__stdcall *QueryInterface)(IDxcBlobUtf8 *This, REFIID riid, void **ppvObject);
|
||||||
|
ULONG(__stdcall *AddRef)(IDxcBlobUtf8 *This);
|
||||||
|
ULONG(__stdcall *Release)(IDxcBlobUtf8 *This);
|
||||||
|
|
||||||
|
LPVOID(__stdcall *GetBufferPointer)(IDxcBlobUtf8 *This);
|
||||||
|
SIZE_T(__stdcall *GetBufferSize)(IDxcBlobUtf8 *This);
|
||||||
|
|
||||||
|
HRESULT(__stdcall *GetEncoding)(IDxcBlobUtf8 *This, BOOL *pKnown, uint32 *pCodePage);
|
||||||
|
|
||||||
|
LPCSTR(__stdcall *GetStringPointer)(IDxcBlobUtf8 *This);
|
||||||
|
SIZE_T(__stdcall *GetStringLength)(IDxcBlobUtf8 *This);
|
||||||
|
};
|
||||||
|
struct IDxcBlobUtf8
|
||||||
|
{
|
||||||
|
IDxcBlobUtf8Vtbl *lpVtbl;
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8 IID_IDxcResult[] = {
|
||||||
|
0xDA, 0x6C, 0x34, 0x58,
|
||||||
|
0xE7, 0xDD,
|
||||||
|
0x97, 0x44,
|
||||||
|
0x94,
|
||||||
|
0x61,
|
||||||
|
0x6F,
|
||||||
|
0x87,
|
||||||
|
0xAF,
|
||||||
|
0x5E,
|
||||||
|
0x06,
|
||||||
|
0x59
|
||||||
|
};
|
||||||
|
using IDxcResult = struct IDxcResult;
|
||||||
|
using IDxcResultVtbl = struct IDxcResultVtbl
|
||||||
|
{
|
||||||
|
HRESULT(__stdcall *QueryInterface)(IDxcResult *This, REFIID riid, void **ppvObject);
|
||||||
|
ULONG(__stdcall *AddRef)(IDxcResult *This);
|
||||||
|
ULONG(__stdcall *Release)(IDxcResult *This);
|
||||||
|
|
||||||
|
HRESULT(__stdcall *GetStatus)(IDxcResult *This, HRESULT *pStatus);
|
||||||
|
HRESULT(__stdcall *GetResult)(IDxcResult *This, IDxcBlob **ppResult);
|
||||||
|
HRESULT(__stdcall *GetErrorBuffer)(IDxcResult *This, IDxcBlobEncoding **ppErrors);
|
||||||
|
|
||||||
|
BOOL(__stdcall *HasOutput)(IDxcResult *This, DXC_OUT_KIND dxcOutKind);
|
||||||
|
HRESULT(__stdcall *GetOutput)(
|
||||||
|
IDxcResult *This,
|
||||||
|
DXC_OUT_KIND dxcOutKind,
|
||||||
|
REFIID iid,
|
||||||
|
void **ppvObject,
|
||||||
|
IDxcBlobWide **ppOutputName
|
||||||
|
);
|
||||||
|
uint32(__stdcall *GetNumOutputs)(IDxcResult *This);
|
||||||
|
DXC_OUT_KIND(__stdcall *GetOutputByIndex)(IDxcResult *This, uint32 Index);
|
||||||
|
DXC_OUT_KIND(__stdcall *PrimaryOutput)(IDxcResult *This);
|
||||||
|
};
|
||||||
|
struct IDxcResult
|
||||||
|
{
|
||||||
|
IDxcResultVtbl *lpVtbl;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
uint32 Data1;
|
||||||
|
uint16 Data2;
|
||||||
|
uint16 Data3;
|
||||||
|
uint8 Data4[8];
|
||||||
|
} CLSID_DxcCompiler = {
|
||||||
|
.Data1 = 0x73e22d93,
|
||||||
|
.Data2 = 0xe6ce,
|
||||||
|
.Data3 = 0x47f3,
|
||||||
|
.Data4 = { 0xb5, 0xbf, 0xf0, 0x66, 0x4f, 0x39, 0xc1, 0xb0 }
|
||||||
|
};
|
||||||
|
static uint8 IID_IDxcCompiler3[] = {
|
||||||
|
0x87, 0x46, 0x8B, 0x22,
|
||||||
|
0x6A, 0x5A,
|
||||||
|
0x30, 0x47,
|
||||||
|
0x90,
|
||||||
|
0x0C,
|
||||||
|
0x97,
|
||||||
|
0x02,
|
||||||
|
0xB2,
|
||||||
|
0x20,
|
||||||
|
0x3F,
|
||||||
|
0x54
|
||||||
|
};
|
||||||
|
using IDxcCompiler3 = struct IDxcCompiler3;
|
||||||
|
using IDxcCompiler3Vtbl = struct IDxcCompiler3Vtbl
|
||||||
|
{
|
||||||
|
HRESULT(__stdcall *QueryInterface)(IDxcCompiler3 *This, REFIID riid, void **ppvObject);
|
||||||
|
ULONG(__stdcall *AddRef)(IDxcCompiler3 *This);
|
||||||
|
ULONG(__stdcall *Release)(IDxcCompiler3 *This);
|
||||||
|
|
||||||
|
HRESULT(__stdcall *Compile)(
|
||||||
|
IDxcCompiler3 *This,
|
||||||
|
const DxcBuffer *pSource,
|
||||||
|
LPCWSTR *pArguments,
|
||||||
|
uint32 argCount,
|
||||||
|
IDxcIncludeHandler *pIncludeHandler,
|
||||||
|
REFIID riid,
|
||||||
|
LPVOID *ppResult
|
||||||
|
);
|
||||||
|
|
||||||
|
HRESULT(__stdcall *Disassemble)(
|
||||||
|
IDxcCompiler3 *This,
|
||||||
|
const DxcBuffer *pObject,
|
||||||
|
REFIID riid,
|
||||||
|
LPVOID *ppResult
|
||||||
|
);
|
||||||
|
};
|
||||||
|
struct IDxcCompiler3
|
||||||
|
{
|
||||||
|
const IDxcCompiler3Vtbl *lpVtbl;
|
||||||
|
};
|
||||||
|
|
||||||
|
// We need all this DxcUtils garbage for DXC include dir support. Thanks Microsoft!
|
||||||
|
using IMalloc = struct IMalloc;
|
||||||
|
using IStream = struct IStream;
|
||||||
|
using DxcDefine = struct DxcDefine;
|
||||||
|
using IDxcCompilerArgs = struct IDxcCompilerArgs;
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
uint32 Data1;
|
||||||
|
uint16 Data2;
|
||||||
|
uint16 Data3;
|
||||||
|
uint8 Data4[8];
|
||||||
|
} CLSID_DxcUtils = {
|
||||||
|
.Data1 = 0x6245d6af,
|
||||||
|
.Data2 = 0x66e0,
|
||||||
|
.Data3 = 0x48fd,
|
||||||
|
.Data4 = {0x80, 0xb4, 0x4d, 0x27, 0x17, 0x96, 0x74, 0x8c}};
|
||||||
|
static uint8 IID_IDxcUtils[] = {
|
||||||
|
0xcb, 0xc4, 0x05, 0x46,
|
||||||
|
0x19, 0x20,
|
||||||
|
0x2a, 0x49,
|
||||||
|
0xad,
|
||||||
|
0xa4,
|
||||||
|
0x65,
|
||||||
|
0xf2,
|
||||||
|
0x0b,
|
||||||
|
0xb7,
|
||||||
|
0xd6,
|
||||||
|
0x7f
|
||||||
|
};
|
||||||
|
using IDxcUtilsVtbl = struct IDxcUtilsVtbl
|
||||||
|
{
|
||||||
|
HRESULT (__stdcall *QueryInterface)(void *pSelf, REFIID riid, void **ppvObject);
|
||||||
|
ULONG (__stdcall *AddRef)(void *pSelf);
|
||||||
|
ULONG (__stdcall *Release)(void *pSelf);
|
||||||
|
|
||||||
|
HRESULT (__stdcall *CreateBlobFromBlob)(void *pSelf, IDxcBlob *pBlob, UINT offset, UINT length, IDxcBlob **ppResult);
|
||||||
|
HRESULT (__stdcall *CreateBlobFromPinned)(void *pSelf, LPCVOID pData, UINT size, UINT codePage, IDxcBlobEncoding **pBlobEncoding);
|
||||||
|
HRESULT (__stdcall *MoveToBlob)(void *pSelf, LPCVOID pData, IMalloc *pIMalloc, UINT size, UINT codePage, IDxcBlobEncoding **pBlobEncoding);
|
||||||
|
HRESULT (__stdcall *CreateBlob)(void *pSelf, LPCVOID pData, UINT size, UINT codePage, IDxcBlobEncoding **pBlobEncoding);
|
||||||
|
HRESULT (__stdcall *LoadFile)(void *pSelf, LPCWSTR pFileName, UINT *pCodePage, IDxcBlobEncoding **pBlobEncoding);
|
||||||
|
HRESULT (__stdcall *CreateReadOnlyStreamFromBlob)(void *pSelf, IDxcBlob *pBlob, IStream **ppStream);
|
||||||
|
HRESULT (__stdcall *CreateDefaultIncludeHandler)(void *pSelf, IDxcIncludeHandler **ppResult);
|
||||||
|
HRESULT (__stdcall *GetBlobAsUtf8)(void *pSelf, IDxcBlob *pBlob, IDxcBlobUtf8 **pBlobEncoding);
|
||||||
|
HRESULT (__stdcall *GetBlobAsWide)(void *pSelf, IDxcBlob *pBlob, IDxcBlobWide **pBlobEncoding);
|
||||||
|
HRESULT (__stdcall *GetDxilContainerPart)(void *pSelf, const DxcBuffer *pShader, UINT DxcPart, void **ppPartData, UINT *pPartSizeInBytes);
|
||||||
|
HRESULT (__stdcall *CreateReflection)(void *pSelf, const DxcBuffer *pData, REFIID iid, void **ppvReflection);
|
||||||
|
HRESULT (__stdcall *BuildArguments)(void *pSelf, LPCWSTR pSourceName, LPCWSTR pEntryPoint, LPCWSTR pTargetProfile, LPCWSTR *pArguments, UINT argCount, const DxcDefine *pDefines, UINT defineCount, IDxcCompilerArgs **ppArgs);
|
||||||
|
HRESULT (__stdcall *GetPDBContents)(void *pSelf, IDxcBlob *pPDBBlob, IDxcBlob **ppHash, IDxcBlob **ppContainer);
|
||||||
|
};
|
||||||
|
|
||||||
|
using IDxcUtils = struct IDxcUtils;
|
||||||
|
struct IDxcUtils
|
||||||
|
{
|
||||||
|
const IDxcUtilsVtbl *lpVtbl;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* *INDENT-ON* */ // clang-format on
|
||||||
|
|
||||||
|
/* DXCompiler */
|
||||||
|
#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) || defined(SDL_PLATFORM_WINDOWS)
|
||||||
|
extern "C" HRESULT __stdcall DxcCreateInstance(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
|
||||||
|
#else
|
||||||
|
extern "C" HRESULT DxcCreateInstance(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
|
||||||
|
#endif
|
||||||
117
JulietShaderCompiler/JulietShaderCompiler.vcxproj
Normal file
117
JulietShaderCompiler/JulietShaderCompiler.vcxproj
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{26880364-45F4-4817-BFD3-0ACC0958757D}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>JulietShaderCompiler</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
|
||||||
|
<PropertyGroup>
|
||||||
|
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>ClangCL</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>ClangCL</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform"/>
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform"/>
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros"/>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)Intermediate\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)Intermediate\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)Juliet\include\;$(SolutionDir)JulietShaderCompiler;</AdditionalIncludeDirectories>
|
||||||
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)\lib\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
<AdditionalDependencies>Juliet.lib; $(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)\lib\$(Platform)\$(Configuration)\;</AdditionalLibraryDirectories>
|
||||||
|
<AdditionalDependencies>Juliet.lib; $(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="main.cpp"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="DXCompiler.h"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<CopyFileToFolders Include="DXShaderCompiler\dxcompiler.dll">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</CopyFileToFolders>
|
||||||
|
<CopyFileToFolders Include="DXShaderCompiler\dxil.dll">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</CopyFileToFolders>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
||||||
22
JulietShaderCompiler/JulietShaderCompiler.vcxproj.filters
Normal file
22
JulietShaderCompiler/JulietShaderCompiler.vcxproj.filters
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="JulietShaderCompiler.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
49
JulietShaderCompiler/main.cpp
Normal file
49
JulietShaderCompiler/main.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#include <Core/Common/String.h>
|
||||||
|
#include <Core/HAL/IO/IOStream.h>
|
||||||
|
#include <Core/Logging/LogManager.h>
|
||||||
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
|
||||||
|
// Must be before everything else.
|
||||||
|
// Cannot include DX12Includes because we redefine everything.
|
||||||
|
// TODO : Separate lib
|
||||||
|
// TODO : Only when not shipping
|
||||||
|
// Check if we just load the dll and not link against?
|
||||||
|
#include <DXCompiler.h>
|
||||||
|
|
||||||
|
#pragma comment(lib, "dxcompiler.lib")
|
||||||
|
|
||||||
|
using namespace Juliet;
|
||||||
|
|
||||||
|
void Compile()
|
||||||
|
{
|
||||||
|
IDxcCompiler3* compiler = nullptr;
|
||||||
|
DxcCreateInstance(&CLSID_DxcCompiler, IID_IDxcCompiler3, reinterpret_cast<void**>(&compiler));
|
||||||
|
|
||||||
|
IDxcUtils* utils = nullptr;
|
||||||
|
DxcCreateInstance(&CLSID_DxcUtils, &IID_IDxcUtils, reinterpret_cast<void**>(&utils));
|
||||||
|
|
||||||
|
if (compiler == nullptr)
|
||||||
|
{
|
||||||
|
Juliet::Log(LogLevel::Error, LogCategory::Graphics, "Cannot create DXCompiler instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utils == nullptr)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics, "Cannot create IDxcUtils instance");
|
||||||
|
compiler->lpVtbl->Release(compiler);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDxcIncludeHandler* includeHandler;
|
||||||
|
utils->lpVtbl->CreateDefaultIncludeHandler(utils, &includeHandler);
|
||||||
|
if (includeHandler == nullptr)
|
||||||
|
{
|
||||||
|
compiler->lpVtbl->Release(compiler);
|
||||||
|
utils->lpVtbl->Release(utils);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
auto* stream = IOFromFile(ConstString("XF"), ConstString("w"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user