working on d3d11 backend

This commit is contained in:
2025-09-05 00:08:58 +02:00
parent 84bb6854c1
commit aceec58473
16 changed files with 269 additions and 68 deletions

View File

@@ -8,11 +8,14 @@
#include "D3D11.h"
#include "D3D11Device.h"
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"d3dcompiler.lib")
PulseBackendFlags Direct3D11CheckSupport(PulseBackendFlags candidates, PulseShaderFormatsFlags shader_formats_used)
{
if(candidates != PULSE_BACKEND_ANY && (candidates & PULSE_BACKEND_D3D11) == 0)
return PULSE_BACKEND_INVALID;
if((shader_formats_used & PULSE_SHADER_FORMAT_DXBC_BIT) == 0)
if((shader_formats_used & PULSE_SHADER_FORMAT_DXBC_BIT) == 0 && (shader_formats_used & PULSE_SHADER_FORMAT_HLSL_BIT) == 0)
return PULSE_BACKEND_INVALID;
return PULSE_BACKEND_D3D11;
}
@@ -28,11 +31,58 @@ void Direct3D11UnloadBackend(PulseBackend backend)
{
}
#ifndef D3D11_ERROR_FILE_NOT_FOUND
#define D3D11_ERROR_FILE_NOT_FOUND 0x887C0002
#endif
#ifndef D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS
#define D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS 0x887C0001
#endif
#ifndef D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS
#define D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS 0x887C0003
#endif
#ifndef D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD
#define D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD 0x887C0004
#endif
#ifndef D3DERR_INVALIDCALL
#define D3DERR_INVALIDCALL 0x887A0001
#endif
#ifndef D3DERR_WASSTILLDRAWING
#define D3DERR_WASSTILLDRAWING 0x887A000A
#endif
const char* D3D11VerbaliseResult(HRESULT res)
{
switch(res)
{
case S_OK:
case S_FALSE: return "success";
case D3D11_ERROR_FILE_NOT_FOUND: return "a file was not found";
case D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS: return "too many instances of a particular state objects";
case D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS: return "too many instances of a particular view objects";
case D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD: return "deffered context mapped without initial discard";
case D3DERR_INVALIDCALL: return "invalid call";
case D3DERR_WASSTILLDRAWING: return "was still drawing";
case E_FAIL: return "attempted to create a device with the debug layer enabled and the layer is not installed";
case E_INVALIDARG: return "an invalid parameter was passed to the returning function";
case E_OUTOFMEMORY: return "could not allocate sufficient memory to complete the call";
case E_NOTIMPL: return "method call isn't implemented with the passed parameter combination";
default: return "Unknown D3D11 error";
}
return "Unknown D3D11 error"; // Just to avoid warnings
}
PulseBackendHandler D3D11Driver = {
.PFN_LoadBackend = Direct3D11LoadBackend,
.PFN_UnloadBackend = Direct3D11UnloadBackend,
.PFN_CreateDevice = Direct3D11CreateDevice,
.backend = PULSE_BACKEND_D3D11,
.supported_shader_formats = PULSE_SHADER_FORMAT_DXBC_BIT,
.supported_shader_formats = PULSE_SHADER_FORMAT_DXBC_BIT | PULSE_SHADER_FORMAT_HLSL_BIT,
.driver_data = PULSE_NULLPTR
};

View File

@@ -9,6 +9,10 @@
#ifndef PULSE_D3D11_H_
#define PULSE_D3D11_H_
#define D3D11_NO_HELPERS
#define CINTERFACE
#define COBJMACROS
#ifdef PULSE_PLAT_WINDOWS
#include <initguid.h>
#endif
@@ -20,6 +24,21 @@
#define D3D11_RETRIEVE_DRIVER_DATA_AS(handle, cast) ((cast)handle->driver_data)
#define CHECK_D3D11_RETVAL(backend, res, error, retval) \
do { \
if((res) != S_OK && (res) != S_FALSE) \
{ \
if(backend != PULSE_NULL_HANDLE && PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(backend)) \
PulseLogErrorFmt(backend, "(D3D11) call to a D3D11 function failed due to %s", D3D11VerbaliseResult(res)); \
PulseSetInternalError(error); \
return retval; \
} \
} while(0) \
#define CHECK_D3D11(backend, res, error) CHECK_D3D11_RETVAL(backend, res, error, )
const char* D3D11VerbaliseResult(HRESULT res);
PulseBackendFlags Direct3D11CheckSupport(PulseBackendFlags candidates, PulseShaderFormatsFlags shader_formats_used); // Returns corresponding PULSE_BACKEND enum in case of success and PULSE_BACKEND_INVALID otherwise
#endif // PULSE_D3D11_H_

View File

@@ -2,18 +2,40 @@
// This file is part of "Pulse"
// For conditions of distribution and use, see copyright notice in LICENSE
#include <string.h>
#include <Pulse.h>
#include <stdlib.h>
#include "../../PulseInternal.h"
#include "D3D11.h"
#include "D3D11Device.h"
#include "D3D11Buffer.h"
#include "D3D11CommandList.h"
PulseBuffer Direct3D11CreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos)
{
Direct3D11Device* d3d11_device = D3D11_RETRIEVE_DRIVER_DATA_AS(device, Direct3D11Device*);
PulseBuffer buffer = (PulseBuffer)calloc(1, sizeof(PulseBufferHandler));
PULSE_CHECK_ALLOCATION_RETVAL(buffer, PULSE_NULL_HANDLE);
Direct3D11Buffer* d3d11_buffer = (Direct3D11Buffer*)calloc(1, sizeof(Direct3D11Buffer));
PULSE_CHECK_ALLOCATION_RETVAL(d3d11_buffer, PULSE_NULL_HANDLE);
buffer->device = device;
buffer->driver_data = d3d11_buffer;
buffer->size = create_infos->size;
buffer->usage = create_infos->usage;
D3D11_BUFFER_DESC description = { 0 };
description.ByteWidth = create_infos->size;
description.Usage = D3D11_USAGE_DEFAULT;
if(create_infos->usage & (PULSE_BUFFER_USAGE_STORAGE_READ | PULSE_BUFFER_USAGE_STORAGE_WRITE))
{
description.BindFlags |= D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
description.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
}
CHECK_D3D11_RETVAL(device->backend, ID3D11Device_CreateBuffer(d3d11_device->device, &description, PULSE_NULLPTR, &d3d11_buffer->buffer), PULSE_ERROR_INITIALIZATION_FAILED, PULSE_NULL_HANDLE);
return buffer;
}
@@ -38,4 +60,8 @@ bool Direct3D11CopyBufferToImage(PulseCommandList cmd, const PulseBufferRegion*
void Direct3D11DestroyBuffer(PulseDevice device, PulseBuffer buffer)
{
Direct3D11Buffer* d3d11_buffer = D3D11_RETRIEVE_DRIVER_DATA_AS(buffer, Direct3D11Buffer*);
ID3D11Buffer_Release(d3d11_buffer->buffer);
free(d3d11_buffer);
free(buffer);
}

View File

@@ -13,7 +13,7 @@
typedef struct Direct3D11Buffer
{
int dummy;
ID3D11Buffer* buffer;
} Direct3D11Buffer;
PulseBuffer Direct3D11CreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos);

View File

@@ -8,10 +8,71 @@
#include "D3D11Device.h"
#include "D3D11ComputePipeline.h"
#include <d3dcompiler.h>
#include <string.h>
static HRESULT CompileComputeShader(PulseDevice device, const unsigned char* src, uint32_t src_size, const char* entry_point, ID3DBlob** blob)
{
if(!src || !entry_point || !device || !blob)
return E_INVALIDARG;
Direct3D11Device* d3d11_device = D3D11_RETRIEVE_DRIVER_DATA_AS(device, Direct3D11Device*);
*blob = PULSE_NULLPTR;
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(device->backend))
flags |= D3DCOMPILE_DEBUG;
// We generally prefer to use the higher CS shader profile when possible as CS 5.0 is better performance on 11-class hardware
LPCSTR profile = (ID3D11Device_GetFeatureLevel(d3d11_device->device) >= D3D_FEATURE_LEVEL_11_0) ? "cs_5_0" : "cs_4_0";
ID3DBlob* shader_blob = PULSE_NULLPTR;
ID3DBlob* error_blob = PULSE_NULLPTR;
HRESULT hr = D3DCompile(src, src_size, PULSE_NULLPTR, PULSE_NULLPTR, PULSE_NULLPTR, entry_point, profile, flags, 0, &shader_blob, &error_blob);
if(FAILED(hr))
{
if(error_blob)
{
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
PulseLogInfoFmt(device->backend, "(D3D11) failed to compile HLSL shader. %s", ID3D10Blob_GetBufferPointer(error_blob));
ID3D10Blob_Release(error_blob);
}
if(shader_blob)
ID3D10Blob_Release(shader_blob);
return hr;
}
*blob = shader_blob;
return hr;
}
PulseComputePipeline Direct3D11CreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info)
{
Direct3D11Device* d3d11_device = D3D11_RETRIEVE_DRIVER_DATA_AS(device, Direct3D11Device*);
PulseComputePipelineHandler* pipeline = (PulseComputePipelineHandler*)calloc(1, sizeof(PulseComputePipelineHandler));
PULSE_CHECK_ALLOCATION_RETVAL(pipeline, PULSE_NULL_HANDLE);
Direct3D11ComputePipeline* d3d11_pipeline = (Direct3D11ComputePipeline*)calloc(1, sizeof(Direct3D11ComputePipeline));
PULSE_CHECK_ALLOCATION_RETVAL(d3d11_pipeline, PULSE_NULL_HANDLE);
pipeline->driver_data = d3d11_pipeline;
ID3D10Blob* blob = PULSE_NULLPTR;
if(info->format & PULSE_SHADER_FORMAT_HLSL_BIT)
CHECK_D3D11_RETVAL(device->backend, CompileComputeShader(device, info->code, info->code_size, info->entrypoint, &blob), PULSE_ERROR_INITIALIZATION_FAILED, PULSE_NULL_HANDLE);
if(blob == PULSE_NULLPTR)
{
D3DCreateBlob(info->code_size, &blob);
memcpy(ID3D10Blob_GetBufferPointer(blob), (void*)info->code, info->code_size);
}
CHECK_D3D11_RETVAL(device->backend, ID3D11Device_CreateComputeShader(d3d11_device->device, ID3D10Blob_GetBufferPointer(blob), ID3D10Blob_GetBufferSize(blob), PULSE_NULLPTR, &d3d11_pipeline->shader), PULSE_ERROR_INITIALIZATION_FAILED, PULSE_NULL_HANDLE);;
ID3D10Blob_Release(blob);
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(device->backend))
PulseLogInfoFmt(device->backend, "(D3D11) created new compute pipeline %p", pipeline);
return pipeline;
@@ -19,4 +80,16 @@ PulseComputePipeline Direct3D11CreateComputePipeline(PulseDevice device, const P
void Direct3D11DestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline)
{
if(pipeline == PULSE_NULL_HANDLE)
{
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
PulseLogWarning(device->backend, "compute pipeline is NULL, this may be a bug in your application");
return;
}
Direct3D11ComputePipeline* d3d11_pipeline = D3D11_RETRIEVE_DRIVER_DATA_AS(pipeline, Direct3D11ComputePipeline*);
ID3D11ComputeShader_Release(d3d11_pipeline->shader);
free(d3d11_pipeline);
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(device->backend))
PulseLogInfoFmt(device->backend, "(D3D11) destroyed compute pipeline %p", pipeline);
free(pipeline);
}

View File

@@ -13,7 +13,7 @@
typedef struct Direct3D11ComputePipeline
{
int dummy;
ID3D11ComputeShader* shader;
} Direct3D11ComputePipeline;
PulseComputePipeline Direct3D11CreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info);

View File

@@ -35,7 +35,7 @@ bool Direct3D11IsDedicatedAdapter(IDXGIAdapter1* adapter)
static uint64_t Direct3D11ScoreAdapter(IDXGIAdapter1* adapter)
{
DXGI_ADAPTER_DESC1 desc;
adapter->lpVtbl->GetDesc1(adapter, &desc);
IDXGIAdapter1_GetDesc1(adapter, &desc);
D3D_FEATURE_LEVEL feature_levels[] = {
D3D_FEATURE_LEVEL_11_1,
@@ -58,10 +58,19 @@ static uint64_t Direct3D11ScoreAdapter(IDXGIAdapter1* adapter)
if(FAILED(hr))
return 0;
hr = base_device->lpVtbl->QueryInterface(base_device, &IID_ID3D11Device1, (void**)&d3d_device1);
hr = ID3D11Device_QueryInterface(base_device, &IID_ID3D11Device1, (void**)&d3d_device1);
if(FAILED(hr) || out_feature_level < D3D_FEATURE_LEVEL_10_0)
goto Cleanup;
// Verify compute shader support presence
if(ID3D11Device_GetFeatureLevel(base_device) < D3D_FEATURE_LEVEL_11_0)
{
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts = { 0 };
ID3D11Device_CheckFeatureSupport(base_device, D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts));
if(!hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x)
goto Cleanup;
}
if(Direct3D11IsDedicatedAdapter(adapter))
score += 50000;
else if(!(desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE))
@@ -77,9 +86,9 @@ static uint64_t Direct3D11ScoreAdapter(IDXGIAdapter1* adapter)
Cleanup:
if(base_device)
base_device->lpVtbl->Release(base_device);
ID3D11Device_Release(base_device);
if(base_context)
base_context->lpVtbl->Release(base_context);
ID3D11DeviceContext_Release(base_context);
return score;
}
@@ -90,11 +99,11 @@ static bool Direct3D11IsAdapterForbidden(IDXGIAdapter1* adapter, PulseDevice* fo
for(uint32_t i = 0; i < forbiden_devices_count; i++)
{
DXGI_ADAPTER_DESC1 desc1;
adapter->lpVtbl->GetDesc1(adapter, &desc1);
IDXGIAdapter1_GetDesc1(adapter, &desc1);
DXGI_ADAPTER_DESC1 desc2;
Direct3D11Device* d3d11_device = D3D11_RETRIEVE_DRIVER_DATA_AS(forbiden_devices[i], Direct3D11Device*);
d3d11_device->adapter->lpVtbl->GetDesc1(d3d11_device->adapter, &desc2);
IDXGIAdapter1_GetDesc1(d3d11_device->adapter, &desc2);
if(desc1.AdapterLuid.HighPart == desc2.AdapterLuid.HighPart && desc1.AdapterLuid.LowPart == desc2.AdapterLuid.LowPart)
return true;
@@ -118,9 +127,9 @@ static IDXGIAdapter1* Direct3D11SelectAdapter(IDXGIFactory1* factory, PulseDevic
best_device_score = current_device_score;
best_device_id = i;
}
adapter->lpVtbl->Release(adapter);
IDXGIAdapter1_Release(adapter);
}
if(factory->lpVtbl->EnumAdapters1(factory, best_device_id, &adapter) == DXGI_ERROR_NOT_FOUND)
if(IDXGIFactory1_EnumAdapters1(factory, best_device_id, &adapter) == DXGI_ERROR_NOT_FOUND)
return PULSE_NULLPTR;
return adapter;
}
@@ -141,7 +150,7 @@ PulseDevice Direct3D11CreateDevice(PulseBackend backend, PulseDevice* forbiden_d
CreateDXGIFactory1(&IID_IDXGIFactory, (void**)&device->factory);
device->adapter = Direct3D11SelectAdapter(device->factory, forbiden_devices, forbiden_devices_count);
device->adapter->lpVtbl->GetDesc1(device->adapter, &device->description);
IDXGIAdapter1_GetDesc1(device->adapter, &device->description);
D3D_FEATURE_LEVEL feature_levels[] = {
D3D_FEATURE_LEVEL_11_1,
@@ -150,7 +159,11 @@ PulseDevice Direct3D11CreateDevice(PulseBackend backend, PulseDevice* forbiden_d
D3D_FEATURE_LEVEL_10_0
};
D3D11CreateDevice((IDXGIAdapter*)device->adapter, D3D_DRIVER_TYPE_UNKNOWN, PULSE_NULLPTR, 0, feature_levels, PULSE_SIZEOF_ARRAY(feature_levels), D3D11_SDK_VERSION, &device->device, PULSE_NULLPTR, &device->context);
UINT flags = 0;
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(backend))
flags |= D3D11_CREATE_DEVICE_DEBUG;
D3D11CreateDevice((IDXGIAdapter*)device->adapter, D3D_DRIVER_TYPE_UNKNOWN, PULSE_NULLPTR, flags, feature_levels, PULSE_SIZEOF_ARRAY(feature_levels), D3D11_SDK_VERSION, &device->device, PULSE_NULLPTR, &device->context);
PULSE_LOAD_DRIVER_DEVICE(Direct3D11);
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(backend))
@@ -163,10 +176,10 @@ void Direct3D11DestroyDevice(PulseDevice device)
Direct3D11Device* d3d11_device = D3D11_RETRIEVE_DRIVER_DATA_AS(device, Direct3D11Device*);
if(d3d11_device == PULSE_NULLPTR || d3d11_device->device == PULSE_NULLPTR)
return;
d3d11_device->device->lpVtbl->Release(d3d11_device->device);
d3d11_device->context->lpVtbl->Release(d3d11_device->context);
d3d11_device->adapter->lpVtbl->Release(d3d11_device->adapter);
d3d11_device->factory->lpVtbl->Release(d3d11_device->factory);
ID3D11Device_Release(d3d11_device->device);
ID3D11DeviceContext_Release(d3d11_device->context);
IDXGIAdapter1_Release(d3d11_device->adapter);
IDXGIFactory1_Release(d3d11_device->factory);
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(device->backend))
PulseLogInfoFmt(device->backend, "(D3D11) destroyed device created from %ls", d3d11_device->description.Description);
free(d3d11_device);

View File

@@ -24,16 +24,6 @@ PulseComputePipeline OpenGLCreateComputePipeline(PulseDevice device, const Pulse
pipeline->driver_data = opengl_pipeline;
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
{
if(info->code == PULSE_NULLPTR)
PulseLogError(device->backend, "invalid code pointer passed to PulseComputePipelineCreateInfo");
if(info->entrypoint == PULSE_NULLPTR)
PulseLogError(device->backend, "invalid entrypoint pointer passed to PulseComputePipelineCreateInfo");
if(info->format == PULSE_SHADER_FORMAT_WGSL_BIT && (device->backend->supported_shader_formats & PULSE_SHADER_FORMAT_WGSL_BIT) == 0)
PulseLogError(device->backend, "invalid shader format passed to PulseComputePipelineCreateInfo");
}
uint8_t* code = (uint8_t*)calloc(info->code_size + 1, 1);
memcpy(code, info->code, info->code_size);

View File

@@ -119,16 +119,6 @@ PulseComputePipeline SoftCreateComputePipeline(PulseDevice device, const PulseCo
SoftComputePipeline* soft_pipeline = (SoftComputePipeline*)calloc(1, sizeof(SoftComputePipeline));
PULSE_CHECK_ALLOCATION_RETVAL(soft_pipeline, PULSE_NULL_HANDLE);
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
{
if(info->code == PULSE_NULLPTR)
PulseLogError(device->backend, "invalid code pointer passed to PulseComputePipelineCreateInfo");
if(info->entrypoint == PULSE_NULLPTR)
PulseLogError(device->backend, "invalid entrypoint pointer passed to PulseComputePipelineCreateInfo");
if(info->format == PULSE_SHADER_FORMAT_SPIRV_BIT && (device->backend->supported_shader_formats & PULSE_SHADER_FORMAT_SPIRV_BIT) == 0)
PulseLogError(device->backend, "invalid shader format passed to PulseComputePipelineCreateInfo");
}
soft_pipeline->program = spvm_program_create(soft_device->spv_context, (spvm_source)info->code, info->code_size / sizeof(spvm_word));
soft_pipeline->entry_point = calloc(1, strlen(info->entrypoint));
PULSE_CHECK_ALLOCATION_RETVAL(soft_pipeline->entry_point, PULSE_NULL_HANDLE);

View File

@@ -19,16 +19,6 @@ PulseComputePipeline VulkanCreateComputePipeline(PulseDevice device, const Pulse
pipeline->driver_data = vulkan_pipeline;
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
{
if(info->code == PULSE_NULLPTR)
PulseLogError(device->backend, "invalid code pointer passed to PulseComputePipelineCreateInfo");
if(info->entrypoint == PULSE_NULLPTR)
PulseLogError(device->backend, "invalid entrypoint pointer passed to PulseComputePipelineCreateInfo");
if(info->format == PULSE_SHADER_FORMAT_SPIRV_BIT && (device->backend->supported_shader_formats & PULSE_SHADER_FORMAT_SPIRV_BIT) == 0)
PulseLogError(device->backend, "invalid shader format passed to PulseComputePipelineCreateInfo");
}
VkShaderModuleCreateInfo shader_module_create_info = { 0 };
shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shader_module_create_info.codeSize = info->code_size;

View File

@@ -335,16 +335,6 @@ PulseComputePipeline WebGPUCreateComputePipeline(PulseDevice device, const Pulse
pipeline->driver_data = webgpu_pipeline;
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
{
if(info->code == PULSE_NULLPTR)
PulseLogError(device->backend, "invalid code pointer passed to PulseComputePipelineCreateInfo");
if(info->entrypoint == PULSE_NULLPTR)
PulseLogError(device->backend, "invalid entrypoint pointer passed to PulseComputePipelineCreateInfo");
if(info->format == PULSE_SHADER_FORMAT_WGSL_BIT && (device->backend->supported_shader_formats & PULSE_SHADER_FORMAT_WGSL_BIT) == 0)
PulseLogError(device->backend, "invalid shader format passed to PulseComputePipelineCreateInfo");
}
WGPUShaderSourceWGSL source = { 0 };
source.chain.next = PULSE_NULLPTR;
source.chain.sType = WGPUSType_ShaderSourceWGSL;

View File

@@ -11,6 +11,15 @@ PULSE_API PulseComputePipeline PulseCreateComputePipeline(PulseDevice device, co
if(info == PULSE_NULLPTR && PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
PulseLogError(device->backend, "null infos pointer");
PULSE_CHECK_PTR_RETVAL(info, PULSE_NULL_HANDLE);
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
{
if(info->code == PULSE_NULLPTR)
PulseLogError(device->backend, "invalid code pointer passed to PulseComputePipelineCreateInfo");
if(info->entrypoint == PULSE_NULLPTR)
PulseLogError(device->backend, "invalid entrypoint pointer passed to PulseComputePipelineCreateInfo");
if((info->format & device->backend->supported_shader_formats) == 0)
PulseLogError(device->backend, "invalid shader format passed to PulseComputePipelineCreateInfo");
}
PulseComputePipeline pipeline = device->PFN_CreateComputePipeline(device, info);
if(pipeline == PULSE_NULL_HANDLE)
return PULSE_NULL_HANDLE;