Support for Windows Subsystem for Linux (#208)

This commit is contained in:
Chuck Walbourn
2021-01-08 02:20:55 -08:00
committed by GitHub
parent 705a8e3766
commit 234eee8a01
27 changed files with 1101 additions and 379 deletions

View File

@@ -20,6 +20,11 @@
#include <cassert>
#include <memory>
#ifndef WIN32
#include <fstream>
#include <filesystem>
#endif
#ifdef __clang__
#pragma clang diagnostic ignored "-Wtautological-type-limit-compare"
#pragma clang diagnostic ignored "-Wcovered-switch-default"
@@ -30,7 +35,12 @@
#pragma warning(disable : 4062)
#define D3DX12_NO_STATE_OBJECT_HELPERS
#ifdef WIN32
#include "d3dx12.h"
#else
#include "directx/d3dx12.h"
#endif
using namespace DirectX;
@@ -43,6 +53,18 @@ using namespace DirectX;
((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))
#endif /* defined(MAKEFOURCC) */
// HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW)
#define HRESULT_E_ARITHMETIC_OVERFLOW static_cast<HRESULT>(0x80070216L)
// HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
#define HRESULT_E_NOT_SUPPORTED static_cast<HRESULT>(0x80070032L)
// HRESULT_FROM_WIN32(ERROR_HANDLE_EOF)
#define HRESULT_E_HANDLE_EOF static_cast<HRESULT>(0x80070026L)
// HRESULT_FROM_WIN32(ERROR_INVALID_DATA)
#define HRESULT_E_INVALID_DATA static_cast<HRESULT>(0x8007000DL)
//--------------------------------------------------------------------------------------
// DDS file structure definitions
//
@@ -124,11 +146,13 @@ struct DDS_HEADER_DXT10
//--------------------------------------------------------------------------------------
namespace
{
#ifdef WIN32
struct handle_closer { void operator()(HANDLE h) noexcept { if (h) CloseHandle(h); } };
using ScopedHandle = std::unique_ptr<void, handle_closer>;
inline HANDLE safe_handle(HANDLE h) noexcept { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; }
#endif
template<UINT TNameLength>
inline void SetDebugObjectName(_In_ ID3D12DeviceChild* resource, _In_z_ const wchar_t(&name)[TNameLength]) noexcept
@@ -239,6 +263,7 @@ namespace
*bitSize = 0;
#ifdef WIN32
// open the file
ScopedHandle hFile(safe_handle(CreateFile2(fileName,
GENERIC_READ,
@@ -296,6 +321,44 @@ namespace
return E_FAIL;
}
size_t len = fileInfo.EndOfFile.LowPart;
#else // !WIN32
std::ifstream inFile(std::filesystem::path(fileName), std::ios::in | std::ios::binary | std::ios::ate);
if (!inFile)
return E_FAIL;
std::streampos fileLen = inFile.tellg();
if (!inFile)
return E_FAIL;
// Need at least enough data to fill the header and magic number to be a valid DDS
if (fileLen < (sizeof(uint32_t) + sizeof(DDS_HEADER)))
return E_FAIL;
ddsData.reset(new (std::nothrow) uint8_t[size_t(fileLen)]);
if (!ddsData)
return E_OUTOFMEMORY;
inFile.seekg(0, std::ios::beg);
if (!inFile)
{
ddsData.reset();
return E_FAIL;
}
inFile.read(reinterpret_cast<char*>(ddsData.get()), fileLen);
if (!inFile)
{
ddsData.reset();
return E_FAIL;
}
inFile.close();
size_t len = fileLen;
#endif
// DDS files always start with the same magic number ("DDS ")
auto dwMagicNumber = *reinterpret_cast<const uint32_t*>(ddsData.get());
if (dwMagicNumber != DDS_MAGIC)
@@ -320,7 +383,7 @@ namespace
(MAKEFOURCC('D', 'X', '1', '0') == hdr->ddspf.fourCC))
{
// Must be long enough for both headers and magic value
if (fileInfo.EndOfFile.LowPart < (sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10)))
if (len < (sizeof(uint32_t) + sizeof(DDS_HEADER) + sizeof(DDS_HEADER_DXT10)))
{
ddsData.reset();
return E_FAIL;
@@ -334,7 +397,7 @@ namespace
auto offset = sizeof(uint32_t) + sizeof(DDS_HEADER)
+ (bDXT10Header ? sizeof(DDS_HEADER_DXT10) : 0);
*bitData = ddsData.get() + offset;
*bitSize = fileInfo.EndOfFile.LowPart - offset;
*bitSize = len - offset;
return S_OK;
}
@@ -619,7 +682,7 @@ namespace
#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_HYBRID_X86_ARM64)
static_assert(sizeof(size_t) == 4, "Not a 32-bit platform!");
if (numBytes > UINT32_MAX || rowBytes > UINT32_MAX || numRows > UINT32_MAX)
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
return HRESULT_E_ARITHMETIC_OVERFLOW;
#else
static_assert(sizeof(size_t) == 8, "Not a 64-bit platform!");
#endif
@@ -1037,7 +1100,7 @@ namespace
return hr;
if (NumBytes > UINT32_MAX || RowBytes > UINT32_MAX)
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
return HRESULT_E_ARITHMETIC_OVERFLOW;
if ((mipCount <= 1) || !maxsize || (w <= maxsize && h <= maxsize && d <= maxsize))
{
@@ -1067,7 +1130,7 @@ namespace
if (pSrcBits + (NumBytes*d) > pEndBits)
{
return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF);
return HRESULT_E_HANDLE_EOF;
}
pSrcBits += NumBytes * d;
@@ -1187,7 +1250,7 @@ namespace
arraySize = d3d10ext->arraySize;
if (arraySize == 0)
{
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
return HRESULT_E_INVALID_DATA;
}
switch (d3d10ext->dxgiFormat)
@@ -1196,12 +1259,12 @@ namespace
case DXGI_FORMAT_IA44:
case DXGI_FORMAT_P8:
case DXGI_FORMAT_A8P8:
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
default:
if (BitsPerPixel(d3d10ext->dxgiFormat) == 0)
{
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
}
@@ -1213,7 +1276,7 @@ namespace
// D3DX writes 1D textures with a fixed Height of 1
if ((header->flags & DDS_HEIGHT) && height != 1)
{
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
return HRESULT_E_INVALID_DATA;
}
height = depth = 1;
break;
@@ -1230,17 +1293,17 @@ namespace
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
if (!(header->flags & DDS_HEADER_FLAGS_VOLUME))
{
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
return HRESULT_E_INVALID_DATA;
}
if (arraySize > 1)
{
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
break;
default:
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
resDim = static_cast<D3D12_RESOURCE_DIMENSION>(d3d10ext->resourceDimension);
@@ -1251,7 +1314,7 @@ namespace
if (format == DXGI_FORMAT_UNKNOWN)
{
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
if (header->flags & DDS_HEADER_FLAGS_VOLUME)
@@ -1265,7 +1328,7 @@ namespace
// We require all six faces to be defined
if ((header->caps2 & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES)
{
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
arraySize = 6;
@@ -1284,7 +1347,7 @@ namespace
// Bound sizes (for security purposes we don't trust DDS file metadata larger than the Direct3D hardware requirements)
if (mipCount > D3D12_REQ_MIP_LEVELS)
{
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
switch (resDim)
@@ -1293,7 +1356,7 @@ namespace
if ((arraySize > D3D12_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) ||
(width > D3D12_REQ_TEXTURE1D_U_DIMENSION))
{
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
break;
@@ -1305,14 +1368,14 @@ namespace
(width > D3D12_REQ_TEXTURECUBE_DIMENSION) ||
(height > D3D12_REQ_TEXTURECUBE_DIMENSION))
{
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
}
else if ((arraySize > D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) ||
(width > D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION) ||
(height > D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION))
{
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
break;
@@ -1322,12 +1385,12 @@ namespace
(height > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION) ||
(depth > D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION))
{
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
break;
default:
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
UINT numberOfPlanes = D3D12GetFormatPlaneCount(d3dDevice, format);
@@ -1337,7 +1400,7 @@ namespace
if ((numberOfPlanes > 1) && IsDepthStencil(format))
{
// DirectX 12 uses planes for stencil, DirectX 11 does not
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
return HRESULT_E_NOT_SUPPORTED;
}
if (outIsCubeMap != nullptr)

View File

@@ -16,7 +16,13 @@
#pragma once
#if defined(WIN32) || defined(WINAPI_FAMILY)
#include <d3d12.h>
#else
#include <wsl/winadapter.h>
#include <wsl/wrladapter.h>
#include <directx/d3d12.h>
#endif
#include <cstddef>
#include <cstdint>