Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@

<!-- ===========================================================-->
<!-- PAL V2.0.1 -->
<!-- =========================================================== -->

## 2.0.1
- Fixed a bug where an internal backend failing to initialize also caused the graphics system to fail. (#5)

<!-- ===========================================================-->
<!-- PAL V2.0.0 -->
<!-- =========================================================== -->
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,17 @@ cd Release

To view additional commands, run the abi dump tool with `--help`.

## Examples
PAL tests are blueprints that can be copy-paste with little code changes. See below for some examples:
- [Triangle Example](./tests/graphics/triangle_test.c)
- [Texture Example](./tests/graphics/texture_test.c)
- [Compute Example](./tests/graphics/compute_test.c)
- [Mesh Example](./tests/graphics/mesh_test.c)
- [Ray Tracing Example](./tests/graphics/ray_tracing_test.c)
- [Custom Graphics Backend Example](./tests/graphics/custom_backend_test.c)
- [Window Example](./tests/video/window_test.c)
- [Input Window Example](./tests/video/input_window_test.c)

## Documentation
PAL uses [Doxygen](https://www.doxygen.nl/) for generating API documentation.

Expand Down
7 changes: 7 additions & 0 deletions src/graphics/d3d12/pal_adapter_d3d12.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ PalResult PAL_CALL enumerateAdaptersD3D12(
uint32_t* count,
PalAdapter** outAdapters)
{
if (!s_D3D12.factory) {
if (!outAdapters) {
*count = 0;
}
return PAL_RESULT_SUCCESS;
}

uint32_t adapterCount = 0;
IDXGIAdapter* adapter = nullptr;
IDXGIAdapter4* dxAdapters[32];
Expand Down
46 changes: 30 additions & 16 deletions src/graphics/d3d12/pal_d3d12.c
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,7 @@ void getDescriptorTierLimitsD3D12(

if (caps) {
*caps = tmp;

} else {
descCaps->maxPerStageSampledImages = tmp.maxPerStageSampledImages;
descCaps->maxPerSetSampledImages = tmp.maxPerSetSampledImages;
Expand Down Expand Up @@ -1051,18 +1052,22 @@ void pollMessagesD3D12(DeviceD3D12* device)
queue->lpVtbl->ClearStoredMessages(queue);
}

PalResult PAL_CALL initGraphicsD3D12(
PalBool PAL_CALL initGraphicsD3D12(
const PalGraphicsDebugger* debugger,
const PalAllocator* allocator)
{
// load d3d12
s_D3D12.handle = LoadLibraryA("d3d12.dll");
s_D3D12.dxgi = LoadLibraryA("dxgi.dll");
if (!s_D3D12.handle || !s_D3D12.dxgi) {
return palMakeResult(
PAL_RESULT_CODE_PLATFORM_FAILURE,
PAL_RESULT_SOURCE_WIN32,
GetLastError());
if (debugger && debugger->callback) {
debugger->callback(
debugger->userData,
PAL_DEBUG_MESSAGE_SEVERITY_ERROR,
PAL_DEBUG_MESSAGE_TYPE_GENERAL,
"Failed to load D3D12 runtime");
}
return PAL_FALSE;
}

// clang-format off
Expand Down Expand Up @@ -1137,27 +1142,36 @@ PalResult PAL_CALL initGraphicsD3D12(
s_D3D12.adapterCount = 0;
HRESULT result = s_D3D12.createDXGIFactory(0, &IID_Factory, (void**)&s_D3D12.factory);
if (FAILED(result)) {
return makeResultD3D12(result);
if (debugger && debugger->callback) {
debugger->callback(
debugger->userData,
PAL_DEBUG_MESSAGE_SEVERITY_ERROR,
PAL_DEBUG_MESSAGE_TYPE_GENERAL,
"Failed to create DXGI Factory");
}
return PAL_FALSE;
}

s_D3D12.allocator = allocator;
return PAL_RESULT_SUCCESS;
return PAL_TRUE;
}

void PAL_CALL shutdownGraphicsD3D12()
{
for (int i = 0; i < s_D3D12.adapterCount; i++) {
s_D3D12.adapters[i].handle->lpVtbl->Release(s_D3D12.adapters[i].handle);
}
if (s_D3D12.factory) {
for (int i = 0; i < s_D3D12.adapterCount; i++) {
s_D3D12.adapters[i].handle->lpVtbl->Release(s_D3D12.adapters[i].handle);
}

s_D3D12.factory->lpVtbl->Release(s_D3D12.factory);
FreeLibrary(s_D3D12.handle);
FreeLibrary(s_D3D12.dxgi);
s_D3D12.factory->lpVtbl->Release(s_D3D12.factory);
FreeLibrary(s_D3D12.handle);
FreeLibrary(s_D3D12.dxgi);

if (s_D3D12.adapters) {
palFree(s_D3D12.allocator, s_D3D12.adapters);
if (s_D3D12.adapters) {
palFree(s_D3D12.allocator, s_D3D12.adapters);
}
memset(&s_D3D12, 0, sizeof(s_D3D12));
}
memset(&s_D3D12, 0, sizeof(s_D3D12));
}

#endif // PAL_HAS_D3D12_BACKEND
151 changes: 49 additions & 102 deletions src/graphics/pal_graphics.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,10 @@ PAL_HANDLE(PalSampler)
PAL_HANDLE(PalSurface)
PAL_HANDLE(PalShaderBindingTable)

typedef struct {
int32_t count;
int32_t startIndex;
PalGraphicsVtable base;
} BackendData;

typedef struct {
int32_t backendCount;
const PalAllocator* allocator;
BackendData backends[MAX_BACKENDS];
PalGraphicsVtable backends[MAX_BACKENDS];
} Graphics;

static Graphics s_Graphics = {0};
Expand Down Expand Up @@ -178,21 +172,26 @@ static PalBool validateVtableVersion1(const PalGraphicsBackendVtable1* vtable1)
return PAL_TRUE;
}

static PalBool addBackend(const PalGraphicsBackendInfo* backendInfo)
static PalBool addBackend(
const void* infoOrVtable,
PalBool custom)
{
BackendData* backendData = &s_Graphics.backends[s_Graphics.backendCount++];
backendData->startIndex = 0;
backendData->count = 0;
PalGraphicsVtable* backend = &s_Graphics.backends[s_Graphics.backendCount++];
memset(backend, 0, sizeof(PalGraphicsVtable));

// populate our internal vtable
if (backendInfo->version == PAL_GRAPHICS_BACKEND_VTABLE_VERSION_1) {
// validate that all version 1 required pointers are set
const PalGraphicsBackendVtable1* vtable1 = (PalGraphicsBackendVtable1*)backendInfo->vtable;
if (!validateVtableVersion1(vtable1)) {
return PAL_FALSE;
if (custom) {
const PalGraphicsBackendInfo* info = infoOrVtable;
if (info->version == PAL_GRAPHICS_BACKEND_VTABLE_VERSION_1) {
// validate that all version 1 required pointers are set
const PalGraphicsBackendVtable1* vtable1 = (PalGraphicsBackendVtable1*)info->vtable;
if (!validateVtableVersion1(vtable1)) {
return PAL_FALSE;
}
backend->vtbl1 = vtable1;
}
memset(&backendData->base, 0, sizeof(PalGraphicsVtable));
backendData->base.vtbl1 = vtable1;

} else {
backend->vtbl1 = infoOrVtable;
}

return PAL_TRUE;
Expand All @@ -204,53 +203,21 @@ PalResult PAL_CALL palInitGraphics(
uint32_t customBackendCount,
const PalGraphicsBackendInfo* customBackends)
{
PalResult result;
BackendData* attachedBackend = nullptr;
#ifdef _WIN32
#if PAL_HAS_D3D12_BACKEND
result = initGraphicsD3D12(debugger, allocator);
if (result != PAL_RESULT_SUCCESS) {
return result;
}

attachedBackend = &s_Graphics.backends[s_Graphics.backendCount++];
attachedBackend->base.vtbl1 = &s_D3D12Backend1;
attachedBackend->startIndex = 0;
attachedBackend->count = 0;
#endif // PAL_HAS_D3D12_BACKEND

#if PAL_HAS_VULKAN_BACKEND
result = initGraphicsVk(debugger, allocator);
if (result != PAL_RESULT_SUCCESS) {
return result;
if (initGraphicsVk(debugger, allocator)) {
addBackend(&s_VkBackend1, PAL_FALSE);
}

attachedBackend = &s_Graphics.backends[s_Graphics.backendCount++];
attachedBackend->base.vtbl1 = &s_VkBackend1;
attachedBackend->startIndex = 0;
attachedBackend->count = 0;
#endif // PAL_HAS_VULKAN_BACKEND

#elif defined(__linux__)
// vulkan
#if PAL_HAS_VULKAN_BACKEND
result = initGraphicsVk(debugger, allocator);
if (result != PAL_RESULT_SUCCESS) {
return result;
#if PAL_HAS_D3D12_BACKEND
if (initGraphicsD3D12(debugger, allocator)) {
addBackend(&s_D3D12Backend1, PAL_FALSE);
}

attachedBackend = &s_Graphics.backends[s_Graphics.backendCount++];
attachedBackend->base.vtbl1 = &s_VkBackend1;
attachedBackend->startIndex = 0;
attachedBackend->count = 0;
#endif // PAL_HAS_VULKAN_BACKEND
#else
// metal or andriod
#endif // _WIN32
#endif // PAL_HAS_D3D12_BACKEND

// custom backends
for (uint32_t i = 0; i < customBackendCount; i++) {
if (!addBackend(&customBackends[i])) {
if (!addBackend(&customBackends[i], PAL_TRUE)) {
return PAL_RESULT_CODE_INVALID_ARGUMENT;
}
}
Expand All @@ -261,24 +228,13 @@ PalResult PAL_CALL palInitGraphics(

void PAL_CALL palShutdownGraphics()
{
#ifdef _WIN32
#if PAL_HAS_D3D12_BACKEND
shutdownGraphicsD3D12();
#endif // PAL_HAS_D3D12_BACKEND

#if PAL_HAS_VULKAN_BACKEND
shutdownGraphicsVk();
#endif // PAL_HAS_VULKAN_BACKEND

#elif defined(__linux__)
// vulkan
#if PAL_HAS_VULKAN_BACKEND
shutdownGraphicsVk();
#endif // PAL_HAS_VULKAN_BACKEND

#else
// metal or andriod
#endif // _WIN32
#if PAL_HAS_D3D12_BACKEND
shutdownGraphicsD3D12();
#endif // PAL_HAS_D3D12_BACKEND

memset(&s_Graphics, 0, sizeof(s_Graphics));
}
Expand All @@ -296,44 +252,35 @@ PalResult PAL_CALL palEnumerateAdapters(
}

// enumerate all adapters for both custom and PAL backends
PalResult result = 0;
int totalCount = 0;
int index = 0;
uint32_t _count = 0;

PalResult result;
uint32_t offset = 0;
uint32_t adapterCount = 0;
for (int i = 0; i < s_Graphics.backendCount; i++) {
BackendData* backend = &s_Graphics.backends[i];
PalGraphicsVtable* backend = &s_Graphics.backends[i];
uint32_t backendAdapterCount = 0;
result = backend->vtbl1->enumerateAdapters(&backendAdapterCount, nullptr);
if (result == PAL_RESULT_SUCCESS) {
adapterCount += backendAdapterCount;
}

if (outAdapters) {
// offset into the array so all backends write at the correct index
PalAdapter** adapters = &outAdapters[backend->startIndex];
_count = backend->count;
result = backend->base.vtbl1->enumerateAdapters(&_count, adapters);
// break if a backend fails
if (result != PAL_RESULT_SUCCESS) {
return result;
PalAdapter** adapters = &outAdapters[offset];
result = backend->vtbl1->enumerateAdapters(&backendAdapterCount, adapters);
if (result == PAL_RESULT_SUCCESS) {
for (int j = 0; j < backendAdapterCount; j++) {
PalAdapter* tmp = adapters[j];
tmp->backend.vtbl1 = backend->vtbl1;
}

// update offset since the backend provided adapters
offset += backendAdapterCount;
}

for (int j = 0; j < _count; j++) {
PalAdapter* tmp = adapters[j];
tmp->backend.vtbl1 = backend->base.vtbl1;
}

} else {
result = backend->base.vtbl1->enumerateAdapters(&_count, nullptr);
// break if a backend fails
if (result != PAL_RESULT_SUCCESS) {
return result;
}

backend->startIndex = totalCount;
backend->count = _count;
totalCount += _count;
_count = 0;
}
}

if (!outAdapters) {
*count = totalCount;
*count = adapterCount;
}
return PAL_RESULT_SUCCESS;
}
Expand Down
4 changes: 2 additions & 2 deletions src/graphics/pal_graphics_backends.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ typedef struct {
// ==================================================

#if PAL_HAS_VULKAN_BACKEND
PalResult PAL_CALL initGraphicsVk(
PalBool PAL_CALL initGraphicsVk(
const PalGraphicsDebugger* debugger,
const PalAllocator* allocator);

Expand Down Expand Up @@ -749,7 +749,7 @@ static PalGraphicsBackendVtable1 s_VkBackend1 = {
// ==================================================

#if PAL_HAS_D3D12_BACKEND
PalResult PAL_CALL initGraphicsD3D12(
PalBool PAL_CALL initGraphicsD3D12(
const PalGraphicsDebugger* debugger,
const PalAllocator* allocator);

Expand Down
7 changes: 7 additions & 0 deletions src/graphics/vulkan/pal_adapter_vulkan.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ PalResult PAL_CALL enumerateAdaptersVk(
uint32_t* count,
PalAdapter** outAdapters)
{
if (!s_Vk.instance) {
if (!outAdapters) {
*count = 0;
}
return PAL_RESULT_SUCCESS;
}

uint32_t deviceCount = 0;
int adapterCount = 0;
uint32_t extCount = 0;
Expand Down
Loading
Loading