forked from LeenkxTeam/LNXRNT
Kinc to Kore
This commit is contained in:
2654
Kore/Backends/Graphics5/Direct3D12/Sources/d3dx12.h
Normal file
2654
Kore/Backends/Graphics5/Direct3D12/Sources/d3dx12.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,626 @@
|
||||
#include "commandlist.h"
|
||||
#include "indexbuffer.h"
|
||||
#include "pipeline.h"
|
||||
#include "vertexbuffer.h"
|
||||
|
||||
#include <kinc/graphics5/graphics.h>
|
||||
#include <kinc/graphics5/pipeline.h>
|
||||
#include <kinc/math/core.h>
|
||||
#include <kinc/window.h>
|
||||
#ifdef KINC_WINDOWS
|
||||
#include <dxgi1_4.h>
|
||||
#undef CreateWindow
|
||||
#endif
|
||||
#include <kinc/system.h>
|
||||
#ifdef KINC_WINDOWS
|
||||
#include <kinc/backend/Windows.h>
|
||||
#endif
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
/*IDXGIFactory4* dxgiFactory;
|
||||
ID3D12Device* device;
|
||||
ID3D12GraphicsCommandList* commandList;
|
||||
ID3D12CommandQueue* commandQueue;
|
||||
ID3D12CommandAllocator* commandAllocators[frameCount];
|
||||
unsigned currentFrame = 0;
|
||||
ID3D12Fence* fence;
|
||||
UINT64 window->current_fence_value[frameCount];
|
||||
HANDLE fenceEvent;
|
||||
ID3D12Resource* renderTargets[frameCount];
|
||||
ID3D12DescriptorHeap* rtvHeap;
|
||||
unsigned rtvDescriptorSize;
|
||||
ID3D12CommandAllocator* bundleAllocator;
|
||||
ID3D12RootSignature* rootSignature;
|
||||
D3D12_VIEWPORT screenViewport;
|
||||
D3D12_RECT scissorRect;
|
||||
ID3D12DescriptorHeap* cbvHeap;*/
|
||||
// ID3D12DeviceContext* context;
|
||||
// ID3D12RenderTargetView* renderTargetView;
|
||||
// ID3D12DepthStencilView* depthStencilView;
|
||||
|
||||
// ID3D12GraphicsCommandList* commandList;
|
||||
|
||||
extern "C" {
|
||||
ID3D12CommandQueue *commandQueue;
|
||||
#ifdef KINC_DIRECT3D_HAS_NO_SWAPCHAIN
|
||||
ID3D12Resource *swapChainRenderTargets[KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT];
|
||||
#else
|
||||
// IDXGISwapChain *swapChain;
|
||||
#endif
|
||||
}
|
||||
|
||||
// int window->width;
|
||||
// int window->height;
|
||||
// int window->new_width;
|
||||
// int window->new_height;
|
||||
|
||||
#ifndef KINC_WINDOWS
|
||||
#define DXGI_SWAP_CHAIN_DESC DXGI_SWAP_CHAIN_DESC1
|
||||
#define IDXGISwapChain IDXGISwapChain1
|
||||
#endif
|
||||
|
||||
struct RenderEnvironment {
|
||||
ID3D12Device *device;
|
||||
ID3D12CommandQueue *queue;
|
||||
#ifdef KINC_DIRECT3D_HAS_NO_SWAPCHAIN
|
||||
ID3D12Resource *renderTargets[KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT];
|
||||
#else
|
||||
IDXGISwapChain *swapChain;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef KINC_WINDOWS
|
||||
#ifdef KINC_DIRECT3D_HAS_NO_SWAPCHAIN
|
||||
extern "C" void createSwapChain(struct RenderEnvironment *env, int bufferCount);
|
||||
#else
|
||||
extern "C" void createSwapChain(struct RenderEnvironment *env, const DXGI_SWAP_CHAIN_DESC1 *desc);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern bool bilinearFiltering;
|
||||
|
||||
// ID3D12Resource* renderTarget;
|
||||
// ID3D12DescriptorHeap* renderTargetDescriptorHeap;
|
||||
|
||||
// static UINT64 window->current_fence_value;
|
||||
// static UINT64 window->current_fence_value[KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT];
|
||||
// static HANDLE window->frame_fence_events[KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT];
|
||||
// static ID3D12Fence *window->frame_fences[KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT];
|
||||
static ID3D12Fence *uploadFence;
|
||||
static ID3D12GraphicsCommandList *initCommandList;
|
||||
static ID3D12CommandAllocator *initCommandAllocator;
|
||||
|
||||
extern "C" struct RenderEnvironment createDeviceAndSwapChainHelper(D3D_FEATURE_LEVEL minimumFeatureLevel, const struct DXGI_SWAP_CHAIN_DESC *swapChainDesc) {
|
||||
struct RenderEnvironment result = {0};
|
||||
#ifdef KINC_WINDOWS
|
||||
kinc_microsoft_affirm(D3D12CreateDevice(NULL, minimumFeatureLevel, IID_PPV_ARGS(&result.device)));
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
|
||||
kinc_microsoft_affirm(result.device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&result.queue)));
|
||||
|
||||
IDXGIFactory4 *dxgiFactory;
|
||||
kinc_microsoft_affirm(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)));
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDescCopy = *swapChainDesc;
|
||||
kinc_microsoft_affirm(dxgiFactory->CreateSwapChain((IUnknown *)result.queue, &swapChainDescCopy, &result.swapChain));
|
||||
#else
|
||||
#ifdef KINC_DIRECT3D_HAS_NO_SWAPCHAIN
|
||||
createSwapChain(&result, KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT);
|
||||
#else
|
||||
createSwapChain(&result, swapChainDesc);
|
||||
#endif
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
static void waitForFence(ID3D12Fence *fence, UINT64 completionValue, HANDLE waitEvent) {
|
||||
if (fence->GetCompletedValue() < completionValue) {
|
||||
kinc_microsoft_affirm(fence->SetEventOnCompletion(completionValue, waitEvent));
|
||||
WaitForSingleObject(waitEvent, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void setupSwapChain(struct dx_window *window) {
|
||||
/*D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
|
||||
heapDesc.NumDescriptors = 1;
|
||||
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
device->CreateDescriptorHeap(&heapDesc, IID_GRAPHICS_PPV_ARGS(&renderTargetDescriptorHeap));*/
|
||||
|
||||
D3D12_RESOURCE_DESC depthTexture = {};
|
||||
depthTexture.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
depthTexture.Alignment = 0;
|
||||
depthTexture.Width = window->width;
|
||||
depthTexture.Height = window->height;
|
||||
depthTexture.DepthOrArraySize = 1;
|
||||
depthTexture.MipLevels = 1;
|
||||
depthTexture.Format = DXGI_FORMAT_D32_FLOAT;
|
||||
depthTexture.SampleDesc.Count = 1;
|
||||
depthTexture.SampleDesc.Quality = 0;
|
||||
depthTexture.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
depthTexture.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL | D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
|
||||
|
||||
D3D12_CLEAR_VALUE clearValue = {};
|
||||
clearValue.Format = DXGI_FORMAT_D32_FLOAT;
|
||||
clearValue.DepthStencil.Depth = 1.0f;
|
||||
clearValue.DepthStencil.Stencil = 0;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProperties = {};
|
||||
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProperties.CreationNodeMask = 1;
|
||||
heapProperties.VisibleNodeMask = 1;
|
||||
|
||||
window->current_fence_value = 0;
|
||||
|
||||
for (int i = 0; i < KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT; ++i) {
|
||||
window->frame_fence_events[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
window->fence_values[i] = 0;
|
||||
device->CreateFence(window->current_fence_value, D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(&window->frame_fences[i]));
|
||||
}
|
||||
|
||||
//**swapChain->GetBuffer(window->current_backbuffer, IID_GRAPHICS_PPV_ARGS(&renderTarget));
|
||||
//**createRenderTargetView();
|
||||
}
|
||||
|
||||
#ifdef KINC_CONSOLE
|
||||
extern "C" void createDeviceAndSwapChain(struct dx_window *window);
|
||||
#else
|
||||
static void createDeviceAndSwapChain(struct dx_window *window) {
|
||||
#ifdef _DEBUG
|
||||
ID3D12Debug *debugController = NULL;
|
||||
D3D12GetDebugInterface(IID_PPV_ARGS(&debugController));
|
||||
debugController->EnableDebugLayer();
|
||||
#endif
|
||||
|
||||
struct DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
||||
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
|
||||
|
||||
swapChainDesc.BufferCount = KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT;
|
||||
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferDesc.Width = window->width;
|
||||
swapChainDesc.BufferDesc.Height = window->height;
|
||||
swapChainDesc.OutputWindow = kinc_windows_window_handle(window->window_index);
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.Windowed = true;
|
||||
|
||||
struct RenderEnvironment renderEnv = createDeviceAndSwapChainHelper(D3D_FEATURE_LEVEL_11_0, &swapChainDesc);
|
||||
|
||||
device = renderEnv.device;
|
||||
commandQueue = renderEnv.queue;
|
||||
|
||||
// swapChain = renderEnv.swapChain;
|
||||
|
||||
setupSwapChain(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void createRootSignature() {
|
||||
ID3DBlob *rootBlob;
|
||||
ID3DBlob *errorBlob;
|
||||
|
||||
D3D12_ROOT_PARAMETER parameters[4] = {};
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE range;
|
||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
range.NumDescriptors = (UINT)KINC_INTERNAL_G5_TEXTURE_COUNT;
|
||||
range.BaseShaderRegister = 0;
|
||||
range.RegisterSpace = 0;
|
||||
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||
parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
parameters[0].DescriptorTable.NumDescriptorRanges = 1;
|
||||
parameters[0].DescriptorTable.pDescriptorRanges = ⦥
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE range2;
|
||||
range2.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||
range2.NumDescriptors = (UINT)KINC_INTERNAL_G5_TEXTURE_COUNT;
|
||||
range2.BaseShaderRegister = 0;
|
||||
range2.RegisterSpace = 0;
|
||||
range2.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||
parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
parameters[1].DescriptorTable.NumDescriptorRanges = 1;
|
||||
parameters[1].DescriptorTable.pDescriptorRanges = &range2;
|
||||
|
||||
parameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
||||
parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
|
||||
parameters[2].Descriptor.ShaderRegister = 0;
|
||||
parameters[2].Descriptor.RegisterSpace = 0;
|
||||
|
||||
parameters[3].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
||||
parameters[3].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
parameters[3].Descriptor.ShaderRegister = 0;
|
||||
parameters[3].Descriptor.RegisterSpace = 0;
|
||||
|
||||
D3D12_STATIC_SAMPLER_DESC samplers[KINC_INTERNAL_G5_TEXTURE_COUNT * 2];
|
||||
for (int i = 0; i < KINC_INTERNAL_G5_TEXTURE_COUNT; ++i) {
|
||||
samplers[i].ShaderRegister = i;
|
||||
samplers[i].Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
samplers[i].AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].MipLODBias = 0;
|
||||
samplers[i].MaxAnisotropy = 16;
|
||||
samplers[i].ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
||||
samplers[i].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;
|
||||
samplers[i].MinLOD = 0.0f;
|
||||
samplers[i].MaxLOD = D3D12_FLOAT32_MAX;
|
||||
samplers[i].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
samplers[i].RegisterSpace = 0;
|
||||
}
|
||||
for (int i = KINC_INTERNAL_G5_TEXTURE_COUNT; i < KINC_INTERNAL_G5_TEXTURE_COUNT * 2; ++i) {
|
||||
samplers[i].ShaderRegister = i;
|
||||
samplers[i].Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
samplers[i].AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].MipLODBias = 0;
|
||||
samplers[i].MaxAnisotropy = 16;
|
||||
samplers[i].ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
||||
samplers[i].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;
|
||||
samplers[i].MinLOD = 0.0f;
|
||||
samplers[i].MaxLOD = D3D12_FLOAT32_MAX;
|
||||
samplers[i].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
samplers[i].RegisterSpace = 0;
|
||||
}
|
||||
|
||||
D3D12_ROOT_SIGNATURE_DESC descRootSignature;
|
||||
descRootSignature.NumParameters = 4;
|
||||
descRootSignature.pParameters = parameters;
|
||||
descRootSignature.NumStaticSamplers = 0;
|
||||
descRootSignature.pStaticSamplers = NULL;
|
||||
descRootSignature.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||
|
||||
kinc_microsoft_affirm(D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, &rootBlob, &errorBlob));
|
||||
device->CreateRootSignature(0, rootBlob->GetBufferPointer(), rootBlob->GetBufferSize(), IID_GRAPHICS_PPV_ARGS(&globalRootSignature));
|
||||
}
|
||||
|
||||
static void createComputeRootSignature() {
|
||||
ID3DBlob *rootBlob;
|
||||
ID3DBlob *errorBlob;
|
||||
|
||||
D3D12_ROOT_PARAMETER parameters[4] = {};
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE range;
|
||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
range.NumDescriptors = (UINT)KINC_INTERNAL_G5_TEXTURE_COUNT;
|
||||
range.BaseShaderRegister = 0;
|
||||
range.RegisterSpace = 0;
|
||||
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||
parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
parameters[0].DescriptorTable.NumDescriptorRanges = 1;
|
||||
parameters[0].DescriptorTable.pDescriptorRanges = ⦥
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE uav_range;
|
||||
uav_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
||||
uav_range.NumDescriptors = (UINT)KINC_INTERNAL_G5_TEXTURE_COUNT;
|
||||
uav_range.BaseShaderRegister = 0;
|
||||
uav_range.RegisterSpace = 0;
|
||||
uav_range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||
parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
parameters[1].DescriptorTable.NumDescriptorRanges = 1;
|
||||
parameters[1].DescriptorTable.pDescriptorRanges = &uav_range;
|
||||
|
||||
D3D12_DESCRIPTOR_RANGE range2;
|
||||
range2.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||
range2.NumDescriptors = (UINT)KINC_INTERNAL_G5_TEXTURE_COUNT;
|
||||
range2.BaseShaderRegister = 0;
|
||||
range2.RegisterSpace = 0;
|
||||
range2.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||
parameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
parameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
parameters[2].DescriptorTable.NumDescriptorRanges = 1;
|
||||
parameters[2].DescriptorTable.pDescriptorRanges = &range2;
|
||||
|
||||
parameters[3].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
||||
parameters[3].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
parameters[3].Descriptor.ShaderRegister = 0;
|
||||
parameters[3].Descriptor.RegisterSpace = 0;
|
||||
|
||||
D3D12_STATIC_SAMPLER_DESC samplers[KINC_INTERNAL_G5_TEXTURE_COUNT * 2];
|
||||
for (int i = 0; i < KINC_INTERNAL_G5_TEXTURE_COUNT; ++i) {
|
||||
samplers[i].ShaderRegister = i;
|
||||
samplers[i].Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
samplers[i].AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].MipLODBias = 0;
|
||||
samplers[i].MaxAnisotropy = 16;
|
||||
samplers[i].ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
||||
samplers[i].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;
|
||||
samplers[i].MinLOD = 0.0f;
|
||||
samplers[i].MaxLOD = D3D12_FLOAT32_MAX;
|
||||
samplers[i].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
samplers[i].RegisterSpace = 0;
|
||||
}
|
||||
for (int i = KINC_INTERNAL_G5_TEXTURE_COUNT; i < KINC_INTERNAL_G5_TEXTURE_COUNT * 2; ++i) {
|
||||
samplers[i].ShaderRegister = i;
|
||||
samplers[i].Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
samplers[i].AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplers[i].MipLODBias = 0;
|
||||
samplers[i].MaxAnisotropy = 16;
|
||||
samplers[i].ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
||||
samplers[i].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;
|
||||
samplers[i].MinLOD = 0.0f;
|
||||
samplers[i].MaxLOD = D3D12_FLOAT32_MAX;
|
||||
samplers[i].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
samplers[i].RegisterSpace = 0;
|
||||
}
|
||||
|
||||
D3D12_ROOT_SIGNATURE_DESC descRootSignature;
|
||||
descRootSignature.NumParameters = 4;
|
||||
descRootSignature.pParameters = parameters;
|
||||
descRootSignature.NumStaticSamplers = 0;
|
||||
descRootSignature.pStaticSamplers = NULL;
|
||||
descRootSignature.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||
|
||||
kinc_microsoft_affirm(D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, &rootBlob, &errorBlob));
|
||||
device->CreateRootSignature(0, rootBlob->GetBufferPointer(), rootBlob->GetBufferSize(), IID_GRAPHICS_PPV_ARGS(&globalComputeRootSignature));
|
||||
|
||||
// createSamplersAndHeaps();
|
||||
}
|
||||
|
||||
static void initialize(struct dx_window *window) {
|
||||
createDeviceAndSwapChain(window);
|
||||
createRootSignature();
|
||||
createComputeRootSignature();
|
||||
|
||||
device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(&uploadFence));
|
||||
|
||||
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(&initCommandAllocator));
|
||||
device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, initCommandAllocator, NULL, IID_GRAPHICS_PPV_ARGS(&initCommandList));
|
||||
|
||||
initCommandList->Close();
|
||||
|
||||
ID3D12CommandList *commandLists[] = {(ID3D12CommandList *)initCommandList};
|
||||
commandQueue->ExecuteCommandLists(1, commandLists);
|
||||
commandQueue->Signal(uploadFence, 1);
|
||||
|
||||
HANDLE waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
waitForFence(uploadFence, 1, waitEvent);
|
||||
|
||||
initCommandAllocator->Reset();
|
||||
initCommandList->Release(); // check me
|
||||
initCommandAllocator->Release(); // check me
|
||||
|
||||
CloseHandle(waitEvent);
|
||||
}
|
||||
|
||||
static void shutdown() {
|
||||
for (int i = 0; i < KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT; ++i) {
|
||||
// waitForFence(window->frame_fences[i], window->current_fence_value[i], window->frame_fence_events[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT; ++i) {
|
||||
// CloseHandle(window->frame_fence_events[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KINC_WINDOWS
|
||||
static void initWindow(struct dx_window *window, int windowIndex) {
|
||||
HWND hwnd = kinc_windows_window_handle(windowIndex);
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
||||
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
|
||||
|
||||
swapChainDesc.BufferCount = KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT;
|
||||
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferDesc.Width = kinc_window_width(windowIndex);
|
||||
swapChainDesc.BufferDesc.Height = kinc_window_height(windowIndex);
|
||||
swapChainDesc.OutputWindow = hwnd;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.Windowed = true;
|
||||
|
||||
IDXGIFactory4 *dxgiFactory = NULL;
|
||||
kinc_microsoft_affirm(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)));
|
||||
|
||||
kinc_microsoft_affirm(dxgiFactory->CreateSwapChain((IUnknown *)commandQueue, &swapChainDesc, &window->swapChain));
|
||||
|
||||
setupSwapChain(window);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g5_internal_destroy_window(int window) {}
|
||||
|
||||
void kinc_g5_internal_destroy() {
|
||||
#ifdef KINC_WINDOWS
|
||||
if (device) {
|
||||
device->Release();
|
||||
device = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g5_internal_init() {
|
||||
#ifdef KINC_WINDOWS
|
||||
#ifdef _DEBUG
|
||||
ID3D12Debug *debugController = NULL;
|
||||
if (D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)) == S_OK) {
|
||||
debugController->EnableDebugLayer();
|
||||
}
|
||||
#endif
|
||||
kinc_microsoft_affirm(D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device)));
|
||||
|
||||
createRootSignature();
|
||||
createComputeRootSignature();
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
|
||||
kinc_microsoft_affirm(device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue)));
|
||||
|
||||
device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&uploadFence));
|
||||
|
||||
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&initCommandAllocator));
|
||||
device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, initCommandAllocator, NULL, IID_PPV_ARGS(&initCommandList));
|
||||
|
||||
initCommandList->Close();
|
||||
|
||||
ID3D12CommandList *commandLists[] = {(ID3D12CommandList *)initCommandList};
|
||||
commandQueue->ExecuteCommandLists(1, commandLists);
|
||||
commandQueue->Signal(uploadFence, 1);
|
||||
|
||||
HANDLE waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
waitForFence(uploadFence, 1, waitEvent);
|
||||
|
||||
initCommandAllocator->Reset();
|
||||
initCommandList->Release(); // check me
|
||||
initCommandAllocator->Release(); // check me
|
||||
|
||||
CloseHandle(waitEvent);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g5_internal_init_window(int windowIndex, int depthBufferBits, int stencilBufferBits, bool verticalSync) {
|
||||
struct dx_window *window = &dx_ctx.windows[windowIndex];
|
||||
window->window_index = windowIndex;
|
||||
window->vsync = verticalSync;
|
||||
window->width = window->new_width = kinc_window_width(windowIndex);
|
||||
window->height = window->new_height = kinc_window_height(windowIndex);
|
||||
#ifdef KINC_WINDOWS
|
||||
initWindow(window, windowIndex);
|
||||
#else
|
||||
HWND hwnd = NULL;
|
||||
window->vsync = verticalSync;
|
||||
window->new_width = window->width = kinc_width();
|
||||
window->new_height = window->height = kinc_height();
|
||||
initialize(window);
|
||||
#endif
|
||||
}
|
||||
|
||||
int kinc_g5_max_bound_textures(void) {
|
||||
return D3D12_COMMONSHADER_SAMPLER_SLOT_COUNT;
|
||||
}
|
||||
|
||||
#ifndef KINC_WINDOWS
|
||||
extern "C" void kinc_internal_wait_for_frame();
|
||||
#endif
|
||||
|
||||
static bool began = false;
|
||||
|
||||
void kinc_g5_begin(kinc_g5_render_target_t *renderTarget, int windowId) {
|
||||
if (began)
|
||||
return;
|
||||
began = true;
|
||||
|
||||
#ifndef KINC_WINDOWS
|
||||
kinc_internal_wait_for_frame();
|
||||
#endif
|
||||
|
||||
struct dx_window *window = &dx_ctx.windows[windowId];
|
||||
dx_ctx.current_window = windowId;
|
||||
|
||||
window->current_backbuffer = (window->current_backbuffer + 1) % KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT;
|
||||
|
||||
const UINT64 fenceValue = window->current_fence_value;
|
||||
commandQueue->Signal(window->frame_fences[window->current_backbuffer], fenceValue);
|
||||
window->fence_values[window->current_backbuffer] = fenceValue;
|
||||
++window->current_fence_value;
|
||||
|
||||
#ifdef KINC_WINDOWSAPP
|
||||
context->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
|
||||
#endif
|
||||
|
||||
waitForFence(window->frame_fences[window->current_backbuffer], window->fence_values[window->current_backbuffer],
|
||||
window->frame_fence_events[window->current_backbuffer]);
|
||||
|
||||
if (window->new_width != window->width || window->new_height != window->height) {
|
||||
#ifndef KINC_DIRECT3D_HAS_NO_SWAPCHAIN
|
||||
kinc_microsoft_affirm(window->swapChain->ResizeBuffers(0, window->new_width, window->new_height, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
|
||||
#endif
|
||||
setupSwapChain(window);
|
||||
window->width = window->new_width;
|
||||
window->height = window->new_height;
|
||||
window->current_backbuffer = 0;
|
||||
}
|
||||
|
||||
// static const float clearColor[] = {0.042f, 0.042f, 0.042f, 1};
|
||||
|
||||
// commandList->ClearRenderTargetView(GetCPUDescriptorHandle(renderTargetDescriptorHeap), clearColor, 0, nullptr);
|
||||
|
||||
// commandList->ClearDepthStencilView(GetCPUDescriptorHandle(depthStencilDescriptorHeap), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
|
||||
|
||||
static int frameNumber = 0;
|
||||
frameNumber++;
|
||||
}
|
||||
|
||||
void kinc_g5_end(int window) {
|
||||
began = false;
|
||||
}
|
||||
|
||||
bool kinc_g5_vsynced() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kinc_window_vsynced(int window) {
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" void kinc_g4_on_g5_internal_resize(int, int, int);
|
||||
|
||||
extern "C" void kinc_internal_resize(int windowId, int width, int height) {
|
||||
if (width == 0 || height == 0)
|
||||
return;
|
||||
struct dx_window *window = &dx_ctx.windows[windowId];
|
||||
window->new_width = width;
|
||||
window->new_height = height;
|
||||
kinc_g4_on_g5_internal_resize(windowId, width, height);
|
||||
}
|
||||
|
||||
extern "C" void kinc_internal_change_framebuffer(int window, kinc_framebuffer_options_t *frame) {}
|
||||
|
||||
#ifndef KINC_DIRECT3D_HAS_NO_SWAPCHAIN
|
||||
bool kinc_g5_swap_buffers() {
|
||||
for (int i = 0; i < MAXIMUM_WINDOWS; i++) {
|
||||
struct dx_window *window = &dx_ctx.windows[i];
|
||||
if (window->swapChain) {
|
||||
kinc_microsoft_affirm(window->swapChain->Present(window->vsync, 0));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g5_flush() {}
|
||||
|
||||
bool kinc_g5_render_targets_inverted_y() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool kinc_g5_supports_raytracing() {
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS5 options;
|
||||
if (device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &options, sizeof(options)) == S_OK) {
|
||||
return options.RaytracingTier >= D3D12_RAYTRACING_TIER_1_0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool kinc_g5_supports_instanced_rendering() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kinc_g5_supports_compute_shaders() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kinc_g5_supports_blend_constants() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kinc_g5_supports_non_pow2_textures() {
|
||||
return true;
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
#include "ShaderHash.h"
|
||||
|
||||
// djb2
|
||||
uint32_t kinc_internal_hash_name(unsigned char *str) {
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
while ((c = *str++)) {
|
||||
hash = hash * 33 ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t hash;
|
||||
uint32_t index;
|
||||
} kinc_internal_hash_index_t;
|
||||
|
||||
uint32_t kinc_internal_hash_name(unsigned char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,620 @@
|
||||
#include <kinc/graphics5/commandlist.h>
|
||||
#include <kinc/graphics5/compute.h>
|
||||
#include <kinc/graphics5/constantbuffer.h>
|
||||
#include <kinc/graphics5/indexbuffer.h>
|
||||
#include <kinc/graphics5/pipeline.h>
|
||||
#include <kinc/graphics5/vertexbuffer.h>
|
||||
#include <kinc/window.h>
|
||||
|
||||
void createHeaps(kinc_g5_command_list_t *list);
|
||||
|
||||
static int formatSize(DXGI_FORMAT format) {
|
||||
switch (format) {
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
return 16;
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||
return 8;
|
||||
case DXGI_FORMAT_R16_FLOAT:
|
||||
return 2;
|
||||
case DXGI_FORMAT_R8_UNORM:
|
||||
return 1;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_init(struct kinc_g5_command_list *list) {
|
||||
#ifndef NDEBUG
|
||||
list->impl.open = false;
|
||||
#endif
|
||||
|
||||
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_GRAPHICS_PPV_ARGS(&list->impl._commandAllocator));
|
||||
device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, list->impl._commandAllocator, NULL, IID_GRAPHICS_PPV_ARGS(&list->impl._commandList));
|
||||
|
||||
list->impl.fence_value = 0;
|
||||
list->impl.fence_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(&list->impl.fence));
|
||||
|
||||
list->impl._indexCount = 0;
|
||||
|
||||
list->impl.current_full_scissor.left = -1;
|
||||
|
||||
for (int i = 0; i < KINC_INTERNAL_G5_TEXTURE_COUNT; ++i) {
|
||||
list->impl.currentRenderTargets[i] = NULL;
|
||||
list->impl.currentTextures[i] = NULL;
|
||||
list->impl.current_samplers[i] = NULL;
|
||||
}
|
||||
list->impl.heapIndex = 0;
|
||||
createHeaps(list);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_destroy(struct kinc_g5_command_list *list) {}
|
||||
|
||||
void kinc_g5_internal_reset_textures(struct kinc_g5_command_list *list);
|
||||
|
||||
void kinc_g5_command_list_begin(struct kinc_g5_command_list *list) {
|
||||
assert(!list->impl.open);
|
||||
|
||||
compute_pipeline_set = false;
|
||||
|
||||
if (list->impl.fence_value > 0) {
|
||||
waitForFence(list->impl.fence, list->impl.fence_value, list->impl.fence_event);
|
||||
list->impl._commandAllocator->Reset();
|
||||
list->impl._commandList->Reset(list->impl._commandAllocator, NULL);
|
||||
}
|
||||
|
||||
kinc_g5_internal_reset_textures(list);
|
||||
|
||||
#ifndef NDEBUG
|
||||
list->impl.open = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_end(struct kinc_g5_command_list *list) {
|
||||
assert(list->impl.open);
|
||||
|
||||
list->impl._commandList->Close();
|
||||
|
||||
#ifndef NDEBUG
|
||||
list->impl.open = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_clear(struct kinc_g5_command_list *list, kinc_g5_render_target_t *renderTarget, unsigned flags, unsigned color, float depth,
|
||||
int stencil) {
|
||||
assert(list->impl.open);
|
||||
|
||||
if (flags & KINC_G5_CLEAR_COLOR) {
|
||||
float clearColor[] = {((color & 0x00ff0000) >> 16) / 255.0f, ((color & 0x0000ff00) >> 8) / 255.0f, (color & 0x000000ff) / 255.0f,
|
||||
((color & 0xff000000) >> 24) / 255.0f};
|
||||
list->impl._commandList->ClearRenderTargetView(renderTarget->impl.renderTargetDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), clearColor, 0,
|
||||
NULL);
|
||||
}
|
||||
if ((flags & KINC_G5_CLEAR_DEPTH) || (flags & KINC_G5_CLEAR_STENCIL)) {
|
||||
D3D12_CLEAR_FLAGS d3dflags = (flags & KINC_G5_CLEAR_DEPTH) && (flags & KINC_G5_CLEAR_STENCIL) ? D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL
|
||||
: (flags & KINC_G5_CLEAR_DEPTH) ? D3D12_CLEAR_FLAG_DEPTH
|
||||
: D3D12_CLEAR_FLAG_STENCIL;
|
||||
|
||||
if (renderTarget->impl.depthStencilDescriptorHeap != NULL) {
|
||||
list->impl._commandList->ClearDepthStencilView(renderTarget->impl.depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), d3dflags, depth,
|
||||
stencil, 0, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_render_target_to_framebuffer_barrier(struct kinc_g5_command_list *list, kinc_g5_render_target_t *renderTarget) {
|
||||
assert(list->impl.open);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier;
|
||||
barrier.Transition.pResource = renderTarget->impl.renderTarget;
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
|
||||
list->impl._commandList->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_framebuffer_to_render_target_barrier(struct kinc_g5_command_list *list, kinc_g5_render_target_t *renderTarget) {
|
||||
assert(list->impl.open);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier;
|
||||
barrier.Transition.pResource = renderTarget->impl.renderTarget;
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
|
||||
list->impl._commandList->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_texture_to_render_target_barrier(struct kinc_g5_command_list *list, kinc_g5_render_target_t *renderTarget) {
|
||||
assert(list->impl.open);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier;
|
||||
barrier.Transition.pResource = renderTarget->impl.renderTarget;
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
|
||||
list->impl._commandList->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_render_target_to_texture_barrier(struct kinc_g5_command_list *list, kinc_g5_render_target_t *renderTarget) {
|
||||
assert(list->impl.open);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier;
|
||||
barrier.Transition.pResource = renderTarget->impl.renderTarget;
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
|
||||
list->impl._commandList->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_vertex_constant_buffer(struct kinc_g5_command_list *list, kinc_g5_constant_buffer_t *buffer, int offset, size_t size) {
|
||||
assert(list->impl.open);
|
||||
|
||||
#ifdef KINC_DXC
|
||||
if (list->impl._currentPipeline->impl.vertexConstantsSize > 0) {
|
||||
if (list->impl._currentPipeline->impl.textures > 0) {
|
||||
list->impl._commandList->SetGraphicsRootConstantBufferView(2, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset);
|
||||
}
|
||||
else {
|
||||
list->impl._commandList->SetGraphicsRootConstantBufferView(0, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset);
|
||||
}
|
||||
}
|
||||
#else
|
||||
list->impl._commandList->SetGraphicsRootConstantBufferView(2, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_fragment_constant_buffer(struct kinc_g5_command_list *list, kinc_g5_constant_buffer_t *buffer, int offset, size_t size) {
|
||||
assert(list->impl.open);
|
||||
#ifdef KINC_DXC
|
||||
if (list->impl._currentPipeline->impl.fragmentConstantsSize > 0) {
|
||||
list->impl._commandList->SetGraphicsRootConstantBufferView(3, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset);
|
||||
}
|
||||
#else
|
||||
list->impl._commandList->SetGraphicsRootConstantBufferView(3, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_compute_constant_buffer(struct kinc_g5_command_list *list, kinc_g5_constant_buffer_t *buffer, int offset, size_t size) {
|
||||
assert(list->impl.open);
|
||||
|
||||
#ifdef KINC_DXC
|
||||
if (list->impl._currentPipeline->impl.fragmentConstantsSize > 0) {
|
||||
list->impl._commandList->SetGraphicsRootConstantBufferView(3, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset);
|
||||
}
|
||||
#else
|
||||
list->impl._commandList->SetComputeRootConstantBufferView(3, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_draw_indexed_vertices(struct kinc_g5_command_list *list) {
|
||||
kinc_g5_command_list_draw_indexed_vertices_from_to(list, 0, list->impl._indexCount);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_draw_indexed_vertices_from_to(struct kinc_g5_command_list *list, int start, int count) {
|
||||
assert(list->impl.open);
|
||||
|
||||
list->impl._commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
/*u8* data;
|
||||
D3D12_RANGE range;
|
||||
range.Begin = currentConstantBuffer * sizeof(vertexConstants);
|
||||
range.End = range.Begin + sizeof(vertexConstants);
|
||||
vertexConstantBuffer->Map(0, &range, (void**)&data);
|
||||
memcpy(data + currentConstantBuffer * sizeof(vertexConstants), vertexConstants, sizeof(vertexConstants));
|
||||
vertexConstantBuffer->Unmap(0, &range);
|
||||
|
||||
range.Begin = currentConstantBuffer * sizeof(fragmentConstants);
|
||||
range.End = range.Begin + sizeof(fragmentConstants);
|
||||
fragmentConstantBuffer->Map(0, &range, (void**)&data);
|
||||
memcpy(data + currentConstantBuffer * sizeof(fragmentConstants), fragmentConstants, sizeof(fragmentConstants));
|
||||
fragmentConstantBuffer->Unmap(0, &range);
|
||||
|
||||
_commandList->SetGraphicsRootConstantBufferView(1, vertexConstantBuffer->GetGPUVirtualAddress() + currentConstantBuffer * sizeof(vertexConstants));
|
||||
_commandList->SetGraphicsRootConstantBufferView(2, fragmentConstantBuffer->GetGPUVirtualAddress() + currentConstantBuffer * sizeof(fragmentConstants));
|
||||
|
||||
++currentConstantBuffer;
|
||||
if (currentConstantBuffer >= constantBufferMultiply) {
|
||||
currentConstantBuffer = 0;
|
||||
}*/
|
||||
|
||||
list->impl._commandList->DrawIndexedInstanced(count, 1, start, 0, 0);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_draw_indexed_vertices_from_to_from(struct kinc_g5_command_list *list, int start, int count, int vertex_offset) {
|
||||
assert(list->impl.open);
|
||||
|
||||
list->impl._commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
list->impl._commandList->DrawIndexedInstanced(count, 1, start, vertex_offset, 0);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_draw_indexed_vertices_instanced(kinc_g5_command_list_t *list, int instanceCount) {
|
||||
kinc_g5_command_list_draw_indexed_vertices_instanced_from_to(list, instanceCount, 0, list->impl._indexCount);
|
||||
}
|
||||
void kinc_g5_command_list_draw_indexed_vertices_instanced_from_to(kinc_g5_command_list_t *list, int instanceCount, int start, int count) {
|
||||
assert(list->impl.open);
|
||||
|
||||
list->impl._commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
list->impl._commandList->DrawIndexedInstanced(count, instanceCount, start, 0, 0);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_execute(kinc_g5_command_list_t *list) {
|
||||
assert(!list->impl.open);
|
||||
|
||||
ID3D12CommandList *commandLists[] = {(ID3D12CommandList *)list->impl._commandList};
|
||||
commandQueue->ExecuteCommandLists(1, commandLists);
|
||||
|
||||
commandQueue->Signal(list->impl.fence, ++list->impl.fence_value);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_wait_for_execution_to_finish(kinc_g5_command_list_t *list) {
|
||||
waitForFence(list->impl.fence, list->impl.fence_value, list->impl.fence_event);
|
||||
}
|
||||
|
||||
bool kinc_g5_non_pow2_textures_supported(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_viewport(struct kinc_g5_command_list *list, int x, int y, int width, int height) {
|
||||
assert(list->impl.open);
|
||||
|
||||
D3D12_VIEWPORT viewport;
|
||||
viewport.TopLeftX = (float)x;
|
||||
viewport.TopLeftY = (float)y;
|
||||
viewport.Width = (float)width;
|
||||
viewport.Height = (float)height;
|
||||
viewport.MinDepth = 0.0f;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
list->impl._commandList->RSSetViewports(1, &viewport);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_scissor(struct kinc_g5_command_list *list, int x, int y, int width, int height) {
|
||||
assert(list->impl.open);
|
||||
|
||||
D3D12_RECT scissor;
|
||||
scissor.left = x;
|
||||
scissor.top = y;
|
||||
scissor.right = x + width;
|
||||
scissor.bottom = y + height;
|
||||
list->impl._commandList->RSSetScissorRects(1, &scissor);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_disable_scissor(struct kinc_g5_command_list *list) {
|
||||
assert(list->impl.open);
|
||||
|
||||
if (list->impl.current_full_scissor.left >= 0) {
|
||||
list->impl._commandList->RSSetScissorRects(1, (D3D12_RECT *)&list->impl.current_full_scissor);
|
||||
}
|
||||
else {
|
||||
D3D12_RECT scissor;
|
||||
scissor.left = 0;
|
||||
scissor.top = 0;
|
||||
scissor.right = kinc_window_width(0);
|
||||
scissor.bottom = kinc_window_height(0);
|
||||
list->impl._commandList->RSSetScissorRects(1, &scissor);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_pipeline(struct kinc_g5_command_list *list, kinc_g5_pipeline_t *pipeline) {
|
||||
assert(list->impl.open);
|
||||
|
||||
list->impl._currentPipeline = pipeline;
|
||||
list->impl._commandList->SetPipelineState(pipeline->impl.pso);
|
||||
compute_pipeline_set = false;
|
||||
|
||||
kinc_g5_internal_setConstants(list, list->impl._currentPipeline);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_blend_constant(kinc_g5_command_list_t *list, float r, float g, float b, float a) {
|
||||
const FLOAT BlendFactor[4] = {r, g, b, a};
|
||||
list->impl._commandList->OMSetBlendFactor(BlendFactor);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_vertex_buffers(struct kinc_g5_command_list *list, kinc_g5_vertex_buffer_t **buffers, int *offsets, int count) {
|
||||
assert(list->impl.open);
|
||||
|
||||
D3D12_VERTEX_BUFFER_VIEW *views = (D3D12_VERTEX_BUFFER_VIEW *)alloca(sizeof(D3D12_VERTEX_BUFFER_VIEW) * count);
|
||||
ZeroMemory(views, sizeof(D3D12_VERTEX_BUFFER_VIEW) * count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
views[i].BufferLocation = buffers[i]->impl.uploadBuffer->GetGPUVirtualAddress() + offsets[i] * kinc_g5_vertex_buffer_stride(buffers[i]);
|
||||
views[i].SizeInBytes = (kinc_g5_vertex_buffer_count(buffers[i]) - offsets[i]) * kinc_g5_vertex_buffer_stride(buffers[i]);
|
||||
views[i].StrideInBytes = kinc_g5_vertex_buffer_stride(buffers[i]); // * kinc_g5_vertex_buffer_count(buffers[i]);
|
||||
}
|
||||
list->impl._commandList->IASetVertexBuffers(0, count, views);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_index_buffer(struct kinc_g5_command_list *list, kinc_g5_index_buffer_t *buffer) {
|
||||
assert(list->impl.open);
|
||||
|
||||
list->impl._indexCount = kinc_g5_index_buffer_count(buffer);
|
||||
list->impl._commandList->IASetIndexBuffer((D3D12_INDEX_BUFFER_VIEW *)&buffer->impl.index_buffer_view);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_render_targets(struct kinc_g5_command_list *list, kinc_g5_render_target_t **targets, int count) {
|
||||
assert(list->impl.open);
|
||||
|
||||
kinc_g5_render_target_t *render_target = targets[0];
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE target_descriptors[16];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
target_descriptors[i] = targets[i]->impl.renderTargetDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
}
|
||||
|
||||
assert(render_target != NULL);
|
||||
|
||||
if (render_target->impl.depthStencilDescriptorHeap != NULL) {
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE heapStart = render_target->impl.depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
list->impl._commandList->OMSetRenderTargets(count, &target_descriptors[0], false, &heapStart);
|
||||
}
|
||||
else {
|
||||
list->impl._commandList->OMSetRenderTargets(count, &target_descriptors[0], false, NULL);
|
||||
}
|
||||
|
||||
list->impl._commandList->RSSetViewports(1, (D3D12_VIEWPORT *)&render_target->impl.viewport);
|
||||
list->impl._commandList->RSSetScissorRects(1, (D3D12_RECT *)&render_target->impl.scissor);
|
||||
|
||||
list->impl.current_full_scissor = render_target->impl.scissor;
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_upload_vertex_buffer(kinc_g5_command_list_t *list, struct kinc_g5_vertex_buffer *buffer) {}
|
||||
|
||||
void kinc_g5_command_list_upload_index_buffer(kinc_g5_command_list_t *list, kinc_g5_index_buffer_t *buffer) {
|
||||
assert(list->impl.open);
|
||||
kinc_g5_internal_index_buffer_upload(buffer, list->impl._commandList);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_upload_texture(kinc_g5_command_list_t *list, kinc_g5_texture_t *texture) {
|
||||
assert(list->impl.open);
|
||||
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER transition = {};
|
||||
transition.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
transition.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
transition.Transition.pResource = texture->impl.image;
|
||||
transition.Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
transition.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
transition.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
|
||||
list->impl._commandList->ResourceBarrier(1, &transition);
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_DESC Desc = texture->impl.image->GetDesc();
|
||||
ID3D12Device *device = NULL;
|
||||
texture->impl.image->GetDevice(IID_GRAPHICS_PPV_ARGS(&device));
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
|
||||
device->GetCopyableFootprints(&Desc, 0, 1, 0, &footprint, NULL, NULL, NULL);
|
||||
device->Release();
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION source = {0};
|
||||
source.pResource = texture->impl.uploadImage;
|
||||
source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
source.PlacedFootprint = footprint;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION destination = {0};
|
||||
destination.pResource = texture->impl.image;
|
||||
destination.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
destination.SubresourceIndex = 0;
|
||||
|
||||
list->impl._commandList->CopyTextureRegion(&destination, 0, 0, 0, &source, NULL);
|
||||
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER transition = {};
|
||||
transition.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
transition.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
transition.Transition.pResource = texture->impl.image;
|
||||
transition.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
transition.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
transition.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
|
||||
list->impl._commandList->ResourceBarrier(1, &transition);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
|
||||
static int d3d12_textureAlignment() {
|
||||
return D3D12_TEXTURE_DATA_PITCH_ALIGNMENT;
|
||||
}
|
||||
#else
|
||||
extern "C" int d3d12_textureAlignment();
|
||||
#endif
|
||||
|
||||
void kinc_g5_command_list_get_render_target_pixels(kinc_g5_command_list_t *list, kinc_g5_render_target_t *render_target, uint8_t *data) {
|
||||
assert(list->impl.open);
|
||||
|
||||
DXGI_FORMAT dxgiFormat = render_target->impl.renderTarget->GetDesc().Format;
|
||||
int formatByteSize = formatSize(dxgiFormat);
|
||||
int rowPitch = render_target->texWidth * formatByteSize;
|
||||
int align = rowPitch % d3d12_textureAlignment();
|
||||
if (align != 0)
|
||||
rowPitch = rowPitch + (d3d12_textureAlignment() - align);
|
||||
|
||||
// Create readback buffer
|
||||
if (render_target->impl.renderTargetReadback == NULL) {
|
||||
D3D12_HEAP_PROPERTIES heapProperties;
|
||||
heapProperties.Type = D3D12_HEAP_TYPE_READBACK;
|
||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProperties.CreationNodeMask = 1;
|
||||
heapProperties.VisibleNodeMask = 1;
|
||||
|
||||
D3D12_RESOURCE_DESC resourceDesc;
|
||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resourceDesc.Alignment = 0;
|
||||
resourceDesc.Width = rowPitch * render_target->texHeight;
|
||||
resourceDesc.Height = 1;
|
||||
resourceDesc.DepthOrArraySize = 1;
|
||||
resourceDesc.MipLevels = 1;
|
||||
resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
resourceDesc.SampleDesc.Count = 1;
|
||||
resourceDesc.SampleDesc.Quality = 0;
|
||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTargetReadback));
|
||||
}
|
||||
|
||||
// Copy render target to readback buffer
|
||||
D3D12_RESOURCE_STATES sourceState = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER barrier;
|
||||
barrier.Transition.pResource = render_target->impl.renderTarget;
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.StateBefore = sourceState;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
list->impl._commandList->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION source;
|
||||
source.pResource = render_target->impl.renderTarget;
|
||||
source.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
source.SubresourceIndex = 0;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dest;
|
||||
dest.pResource = render_target->impl.renderTargetReadback;
|
||||
dest.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
dest.PlacedFootprint.Offset = 0;
|
||||
dest.PlacedFootprint.Footprint.Format = dxgiFormat;
|
||||
dest.PlacedFootprint.Footprint.Width = render_target->texWidth;
|
||||
dest.PlacedFootprint.Footprint.Height = render_target->texHeight;
|
||||
dest.PlacedFootprint.Footprint.Depth = 1;
|
||||
dest.PlacedFootprint.Footprint.RowPitch = rowPitch;
|
||||
|
||||
list->impl._commandList->CopyTextureRegion(&dest, 0, 0, 0, &source, NULL);
|
||||
|
||||
{
|
||||
D3D12_RESOURCE_BARRIER barrier;
|
||||
barrier.Transition.pResource = render_target->impl.renderTarget;
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
barrier.Transition.StateAfter = sourceState;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
list->impl._commandList->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
kinc_g5_command_list_end(list);
|
||||
kinc_g5_command_list_execute(list);
|
||||
kinc_g5_command_list_wait_for_execution_to_finish(list);
|
||||
kinc_g5_command_list_begin(list);
|
||||
|
||||
// Read buffer
|
||||
void *p;
|
||||
render_target->impl.renderTargetReadback->Map(0, NULL, &p);
|
||||
memcpy(data, p, render_target->texWidth * render_target->texHeight * formatByteSize);
|
||||
render_target->impl.renderTargetReadback->Unmap(0, NULL);
|
||||
}
|
||||
|
||||
void kinc_g5_internal_set_compute_constants(kinc_g5_command_list_t *commandList);
|
||||
|
||||
void kinc_g5_command_list_set_compute_shader(kinc_g5_command_list_t *list, kinc_g5_compute_shader *shader) {
|
||||
list->impl._commandList->SetPipelineState(shader->impl.pso);
|
||||
compute_pipeline_set = true;
|
||||
|
||||
for (int i = 0; i < KINC_INTERNAL_G5_TEXTURE_COUNT; ++i) {
|
||||
list->impl.currentRenderTargets[i] = NULL;
|
||||
list->impl.currentTextures[i] = NULL;
|
||||
}
|
||||
kinc_g5_internal_set_compute_constants(list);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_compute(kinc_g5_command_list_t *list, int x, int y, int z) {
|
||||
assert(list->impl.open);
|
||||
list->impl._commandList->Dispatch(x, y, z);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_render_target_face(kinc_g5_command_list_t *list, kinc_g5_render_target_t *texture, int face) {}
|
||||
|
||||
void kinc_g5_command_list_set_texture(kinc_g5_command_list_t *list, kinc_g5_texture_unit_t unit, kinc_g5_texture_t *texture) {
|
||||
if (unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
kinc_g5_internal_texture_set(list, texture, unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT]);
|
||||
}
|
||||
else if (unit.stages[KINC_G5_SHADER_TYPE_VERTEX] >= 0) {
|
||||
kinc_g5_internal_texture_set(list, texture, unit.stages[KINC_G5_SHADER_TYPE_VERTEX]);
|
||||
}
|
||||
else if (unit.stages[KINC_G5_SHADER_TYPE_COMPUTE] >= 0) {
|
||||
kinc_g5_internal_texture_set(list, texture, unit.stages[KINC_G5_SHADER_TYPE_COMPUTE]);
|
||||
}
|
||||
kinc_g5_internal_set_textures(list);
|
||||
}
|
||||
|
||||
void kinc_g5_internal_sampler_set(kinc_g5_command_list_t *list, kinc_g5_sampler_t *sampler, int unit);
|
||||
|
||||
void kinc_g5_command_list_set_sampler(kinc_g5_command_list_t *list, kinc_g5_texture_unit_t unit, kinc_g5_sampler_t *sampler) {
|
||||
if (unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
kinc_g5_internal_sampler_set(list, sampler, unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT]);
|
||||
}
|
||||
else if (unit.stages[KINC_G5_SHADER_TYPE_VERTEX] >= 0) {
|
||||
kinc_g5_internal_sampler_set(list, sampler, unit.stages[KINC_G5_SHADER_TYPE_VERTEX]);
|
||||
}
|
||||
kinc_g5_internal_set_textures(list);
|
||||
}
|
||||
|
||||
bool kinc_g5_command_list_init_occlusion_query(kinc_g5_command_list_t *list, unsigned *occlusionQuery) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_image_texture(kinc_g5_command_list_t *list, kinc_g5_texture_unit_t unit, kinc_g5_texture_t *texture) {
|
||||
if (unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
kinc_g5_internal_texture_set(list, texture, unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT]);
|
||||
}
|
||||
else if (unit.stages[KINC_G5_SHADER_TYPE_VERTEX] >= 0) {
|
||||
kinc_g5_internal_texture_set(list, texture, unit.stages[KINC_G5_SHADER_TYPE_VERTEX]);
|
||||
}
|
||||
else if (unit.stages[KINC_G5_SHADER_TYPE_COMPUTE] >= 0) {
|
||||
kinc_g5_internal_texture_set(list, texture, unit.stages[KINC_G5_SHADER_TYPE_COMPUTE]);
|
||||
}
|
||||
kinc_g5_internal_set_textures(list);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_delete_occlusion_query(kinc_g5_command_list_t *list, unsigned occlusionQuery) {}
|
||||
|
||||
void kinc_g5_command_list_render_occlusion_query(kinc_g5_command_list_t *list, unsigned occlusionQuery, int triangles) {}
|
||||
|
||||
bool kinc_g5_command_list_are_query_results_available(kinc_g5_command_list_t *list, unsigned occlusionQuery) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_get_query_result(kinc_g5_command_list_t *list, unsigned occlusionQuery, unsigned *pixelCount) {}
|
||||
|
||||
void kinc_g5_command_list_set_texture_from_render_target(kinc_g5_command_list_t *list, kinc_g5_texture_unit_t unit, kinc_g5_render_target_t *target) {
|
||||
if (unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
target->impl.stage = unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT];
|
||||
list->impl.currentRenderTargets[target->impl.stage] = target;
|
||||
}
|
||||
else if (unit.stages[KINC_G5_SHADER_TYPE_VERTEX] >= 0) {
|
||||
target->impl.stage = unit.stages[KINC_G5_SHADER_TYPE_VERTEX];
|
||||
list->impl.currentRenderTargets[target->impl.stage] = target;
|
||||
}
|
||||
list->impl.currentTextures[target->impl.stage] = NULL;
|
||||
|
||||
kinc_g5_internal_set_textures(list);
|
||||
}
|
||||
|
||||
void kinc_g5_command_list_set_texture_from_render_target_depth(kinc_g5_command_list_t *list, kinc_g5_texture_unit_t unit, kinc_g5_render_target_t *target) {
|
||||
if (unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
target->impl.stage_depth = unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT];
|
||||
list->impl.currentRenderTargets[target->impl.stage_depth] = target;
|
||||
}
|
||||
else if (unit.stages[KINC_G5_SHADER_TYPE_VERTEX] >= 0) {
|
||||
target->impl.stage_depth = unit.stages[KINC_G5_SHADER_TYPE_VERTEX];
|
||||
list->impl.currentRenderTargets[target->impl.stage_depth] = target;
|
||||
}
|
||||
list->impl.currentTextures[target->impl.stage_depth] = NULL;
|
||||
|
||||
kinc_g5_internal_set_textures(list);
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "d3d12mini.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct kinc_g5_pipeline;
|
||||
struct kinc_g5_render_target;
|
||||
struct kinc_g5_texture;
|
||||
struct kinc_g5_sampler;
|
||||
|
||||
#define KINC_INTERNAL_G5_TEXTURE_COUNT 16
|
||||
|
||||
typedef struct {
|
||||
struct ID3D12CommandAllocator *_commandAllocator;
|
||||
struct ID3D12GraphicsCommandList *_commandList;
|
||||
struct kinc_g5_pipeline *_currentPipeline;
|
||||
int _indexCount;
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool open;
|
||||
#endif
|
||||
|
||||
struct D3D12Rect current_full_scissor;
|
||||
|
||||
// keep track of when a command-list is done
|
||||
uint64_t fence_value;
|
||||
struct ID3D12Fence *fence;
|
||||
HANDLE fence_event;
|
||||
|
||||
struct kinc_g5_render_target *currentRenderTargets[KINC_INTERNAL_G5_TEXTURE_COUNT];
|
||||
struct kinc_g5_texture *currentTextures[KINC_INTERNAL_G5_TEXTURE_COUNT];
|
||||
struct kinc_g5_sampler *current_samplers[KINC_INTERNAL_G5_TEXTURE_COUNT];
|
||||
|
||||
int heapIndex;
|
||||
struct ID3D12DescriptorHeap *srvHeap;
|
||||
struct ID3D12DescriptorHeap *samplerHeap;
|
||||
} CommandList5Impl;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,167 @@
|
||||
#include <kinc/graphics5/compute.h>
|
||||
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
void kinc_g5_compute_shader_init(kinc_g5_compute_shader *shader, void *_data, int length) {
|
||||
unsigned index = 0;
|
||||
uint8_t *data = (uint8_t *)_data;
|
||||
|
||||
memset(&shader->impl.attributes, 0, sizeof(shader->impl.attributes));
|
||||
int attributesCount = data[index++];
|
||||
for (int i = 0; i < attributesCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.attributes[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.attributes[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.textures, 0, sizeof(shader->impl.textures));
|
||||
uint8_t texCount = data[index++];
|
||||
for (unsigned i = 0; i < texCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.textures[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.textures[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.constants, 0, sizeof(shader->impl.constants));
|
||||
uint8_t constantCount = data[index++];
|
||||
shader->impl.constantsSize = 0;
|
||||
for (unsigned i = 0; i < constantCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
kinc_compute_internal_shader_constant_t constant;
|
||||
constant.hash = kinc_internal_hash_name(name);
|
||||
memcpy(&constant.offset, &data[index], sizeof(constant.offset));
|
||||
index += 4;
|
||||
memcpy(&constant.size, &data[index], sizeof(constant.size));
|
||||
index += 4;
|
||||
constant.columns = data[index];
|
||||
index += 1;
|
||||
constant.rows = data[index];
|
||||
index += 1;
|
||||
|
||||
shader->impl.constants[i] = constant;
|
||||
shader->impl.constantsSize = constant.offset + constant.size;
|
||||
}
|
||||
|
||||
shader->impl.length = (int)(length - index);
|
||||
shader->impl.data = (uint8_t *)malloc(shader->impl.length);
|
||||
assert(shader->impl.data != NULL);
|
||||
memcpy(shader->impl.data, &data[index], shader->impl.length);
|
||||
|
||||
D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {0};
|
||||
desc.CS.BytecodeLength = shader->impl.length;
|
||||
desc.CS.pShaderBytecode = shader->impl.data;
|
||||
desc.pRootSignature = globalComputeRootSignature;
|
||||
HRESULT hr = device->CreateComputePipelineState(&desc, IID_GRAPHICS_PPV_ARGS(&shader->impl.pso));
|
||||
|
||||
if (hr != S_OK) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not initialize compute shader.");
|
||||
return;
|
||||
}
|
||||
|
||||
// kinc_microsoft_affirm(device->CreateBuffer(&CD3D11_BUFFER_DESC(getMultipleOf16(shader->impl.constantsSize), D3D11_BIND_CONSTANT_BUFFER), nullptr,
|
||||
// &shader->impl.constantBuffer));
|
||||
}
|
||||
|
||||
void kinc_g5_compute_shader_destroy(kinc_g5_compute_shader *shader) {
|
||||
if (shader->impl.pso != NULL) {
|
||||
shader->impl.pso->Release();
|
||||
shader->impl.pso = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static kinc_compute_internal_shader_constant_t *findComputeConstant(kinc_compute_internal_shader_constant_t *constants, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (constants[i].hash == hash) {
|
||||
return &constants[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static kinc_internal_hash_index_t *findComputeTextureUnit(kinc_internal_hash_index_t *units, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (units[i].hash == hash) {
|
||||
return &units[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kinc_g5_constant_location_t kinc_g5_compute_shader_get_constant_location(kinc_g5_compute_shader *shader, const char *name) {
|
||||
kinc_g5_constant_location_t location = {0};
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
|
||||
|
||||
kinc_compute_internal_shader_constant_t *constant = findComputeConstant(shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.computeOffset = 0;
|
||||
location.impl.computeSize = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.computeOffset = constant->offset;
|
||||
location.impl.computeSize = constant->size;
|
||||
}
|
||||
|
||||
if (location.impl.computeSize == 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_g5_texture_unit_t kinc_g5_compute_shader_get_texture_unit(kinc_g5_compute_shader *shader, const char *name) {
|
||||
char unitName[64];
|
||||
int unitOffset = 0;
|
||||
size_t len = strlen(name);
|
||||
if (len > 63)
|
||||
len = 63;
|
||||
strncpy(unitName, name, len + 1);
|
||||
if (unitName[len - 1] == ']') { // Check for array - mySampler[2]
|
||||
unitOffset = (int)(unitName[len - 2] - '0'); // Array index is unit offset
|
||||
unitName[len - 3] = 0; // Strip array from name
|
||||
}
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)unitName);
|
||||
|
||||
kinc_g5_texture_unit_t unit;
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
unit.stages[i] = -1;
|
||||
}
|
||||
kinc_internal_hash_index_t *computeUnit = findComputeTextureUnit(shader->impl.textures, hash);
|
||||
if (computeUnit == NULL) {
|
||||
#ifndef NDEBUG
|
||||
static int notFoundCount = 0;
|
||||
if (notFoundCount < 10) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Sampler %s not found.", unitName);
|
||||
++notFoundCount;
|
||||
}
|
||||
else if (notFoundCount == 10) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Giving up on sampler not found messages.", unitName);
|
||||
++notFoundCount;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
unit.stages[KINC_G5_SHADER_TYPE_COMPUTE] = computeUnit->index + unitOffset;
|
||||
}
|
||||
return unit;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/backend/graphics5/ShaderHash.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t hash;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
uint8_t columns;
|
||||
uint8_t rows;
|
||||
} kinc_compute_internal_shader_constant_t;
|
||||
|
||||
typedef struct kinc_g5_compute_shader_impl {
|
||||
kinc_compute_internal_shader_constant_t constants[64];
|
||||
int constantsSize;
|
||||
kinc_internal_hash_index_t attributes[64];
|
||||
kinc_internal_hash_index_t textures[64];
|
||||
uint8_t *data;
|
||||
int length;
|
||||
struct ID3D12Buffer *constantBuffer;
|
||||
struct ID3D12PipelineState *pso;
|
||||
} kinc_g5_compute_shader_impl;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,70 @@
|
||||
#include <kinc/graphics5/constantbuffer.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
bool kinc_g5_transposeMat3 = false;
|
||||
bool kinc_g5_transposeMat4 = false;
|
||||
|
||||
void kinc_g5_constant_buffer_init(kinc_g5_constant_buffer_t *buffer, int size) {
|
||||
buffer->impl.mySize = size;
|
||||
buffer->data = NULL;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProperties;
|
||||
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProperties.CreationNodeMask = 1;
|
||||
heapProperties.VisibleNodeMask = 1;
|
||||
|
||||
D3D12_RESOURCE_DESC resourceDesc;
|
||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resourceDesc.Alignment = 0;
|
||||
resourceDesc.Width = size;
|
||||
resourceDesc.Height = 1;
|
||||
resourceDesc.DepthOrArraySize = 1;
|
||||
resourceDesc.MipLevels = 1;
|
||||
resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
resourceDesc.SampleDesc.Count = 1;
|
||||
resourceDesc.SampleDesc.Quality = 0;
|
||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
kinc_microsoft_affirm(device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&buffer->impl.constant_buffer)));
|
||||
|
||||
void *p;
|
||||
buffer->impl.constant_buffer->Map(0, NULL, &p);
|
||||
ZeroMemory(p, size);
|
||||
buffer->impl.constant_buffer->Unmap(0, NULL);
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_destroy(kinc_g5_constant_buffer_t *buffer) {
|
||||
buffer->impl.constant_buffer->Release();
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_lock_all(kinc_g5_constant_buffer_t *buffer) {
|
||||
kinc_g5_constant_buffer_lock(buffer, 0, kinc_g5_constant_buffer_size(buffer));
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_lock(kinc_g5_constant_buffer_t *buffer, int start, int count) {
|
||||
buffer->impl.lastStart = start;
|
||||
buffer->impl.lastCount = count;
|
||||
D3D12_RANGE range;
|
||||
range.Begin = start;
|
||||
range.End = range.Begin + count;
|
||||
uint8_t *p;
|
||||
buffer->impl.constant_buffer->Map(0, &range, (void **)&p);
|
||||
buffer->data = &p[start];
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_unlock(kinc_g5_constant_buffer_t *buffer) {
|
||||
D3D12_RANGE range;
|
||||
range.Begin = buffer->impl.lastStart;
|
||||
range.End = range.Begin + buffer->impl.lastCount;
|
||||
buffer->impl.constant_buffer->Unmap(0, &range);
|
||||
buffer->data = NULL;
|
||||
}
|
||||
|
||||
int kinc_g5_constant_buffer_size(kinc_g5_constant_buffer_t *buffer) {
|
||||
return buffer->impl.mySize;
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D12Resource;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D12Resource *constant_buffer;
|
||||
int lastStart;
|
||||
int lastCount;
|
||||
int mySize;
|
||||
} ConstantBuffer5Impl;
|
||||
|
||||
KINC_FUNC extern bool kinc_g5_transposeMat3;
|
||||
KINC_FUNC extern bool kinc_g5_transposeMat4;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D12CommandAllocator;
|
||||
struct ID3D12GraphicsCommandList;
|
||||
struct ID3D12Fence;
|
||||
struct ID3D12Resource;
|
||||
struct ID3D12DescriptorHeap;
|
||||
struct IDXGISwapChain;
|
||||
|
||||
typedef void *HANDLE;
|
||||
typedef unsigned __int64 UINT64;
|
||||
|
||||
struct D3D12Viewport {
|
||||
float TopLeftX;
|
||||
float TopLeftY;
|
||||
float Width;
|
||||
float Height;
|
||||
float MinDepth;
|
||||
float MaxDepth;
|
||||
};
|
||||
|
||||
struct D3D12Rect {
|
||||
long left;
|
||||
long top;
|
||||
long right;
|
||||
long bottom;
|
||||
};
|
||||
|
||||
#define KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT 2
|
||||
|
||||
struct dx_window {
|
||||
#ifndef KINC_DIRECT3D_HAS_NO_SWAPCHAIN
|
||||
struct IDXGISwapChain *swapChain;
|
||||
#endif
|
||||
UINT64 current_fence_value;
|
||||
UINT64 fence_values[KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT];
|
||||
HANDLE frame_fence_events[KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT];
|
||||
struct ID3D12Fence *frame_fences[KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT];
|
||||
int width;
|
||||
int height;
|
||||
int new_width;
|
||||
int new_height;
|
||||
int current_backbuffer;
|
||||
bool vsync;
|
||||
int window_index;
|
||||
};
|
||||
|
||||
struct dx_window *kinc_dx_current_window();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,106 @@
|
||||
#include <kinc/global.h>
|
||||
|
||||
// Windows 7
|
||||
#define WINVER 0x0601
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#define NOATOM
|
||||
#define NOCLIPBOARD
|
||||
#define NOCOLOR
|
||||
#define NOCOMM
|
||||
#define NOCTLMGR
|
||||
#define NODEFERWINDOWPOS
|
||||
#define NODRAWTEXT
|
||||
#define NOGDI
|
||||
#define NOGDICAPMASKS
|
||||
#define NOHELP
|
||||
#define NOICONS
|
||||
#define NOKANJI
|
||||
#define NOKEYSTATES
|
||||
#define NOMB
|
||||
#define NOMCX
|
||||
#define NOMEMMGR
|
||||
#define NOMENUS
|
||||
#define NOMETAFILE
|
||||
#define NOMINMAX
|
||||
// #define NOMSG
|
||||
#define NONLS
|
||||
#define NOOPENFILE
|
||||
#define NOPROFILER
|
||||
#define NORASTEROPS
|
||||
#define NOSCROLL
|
||||
#define NOSERVICE
|
||||
#define NOSHOWWINDOW
|
||||
#define NOSOUND
|
||||
#define NOSYSCOMMANDS
|
||||
#define NOSYSMETRICS
|
||||
#define NOTEXTMETRIC
|
||||
// #define NOUSER
|
||||
#define NOVIRTUALKEYCODES
|
||||
#define NOWH
|
||||
#define NOWINMESSAGES
|
||||
#define NOWINOFFSETS
|
||||
#define NOWINSTYLES
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#ifdef KINC_WINDOWS
|
||||
#include <d3d12.h>
|
||||
#else
|
||||
#include <kinc/backend/d3d12_special_edition.h>
|
||||
#endif
|
||||
#ifdef KINC_DIRECT3D_HAS_NO_SWAPCHAIN
|
||||
struct DXGI_SWAP_CHAIN_DESC1;
|
||||
#else
|
||||
#include <dxgi.h>
|
||||
#endif
|
||||
|
||||
#include "d3d12mini.h"
|
||||
|
||||
#ifndef IID_GRAPHICS_PPV_ARGS
|
||||
#define IID_GRAPHICS_PPV_ARGS(x) IID_PPV_ARGS(x)
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
ID3D12Device *device = NULL;
|
||||
}
|
||||
static ID3D12RootSignature *globalRootSignature = NULL;
|
||||
static ID3D12RootSignature *globalComputeRootSignature = NULL;
|
||||
// extern ID3D12GraphicsCommandList* commandList;
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAXIMUM_WINDOWS 16
|
||||
|
||||
struct dx_ctx {
|
||||
int current_window;
|
||||
struct dx_window windows[MAXIMUM_WINDOWS];
|
||||
};
|
||||
|
||||
static struct dx_ctx dx_ctx = {0};
|
||||
|
||||
struct dx_window *kinc_dx_current_window() {
|
||||
return &dx_ctx.windows[dx_ctx.current_window];
|
||||
}
|
||||
|
||||
static bool compute_pipeline_set = false;
|
||||
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "Direct3D12.c.h"
|
||||
#include "ShaderHash.c.h"
|
||||
#include "commandlist.c.h"
|
||||
#include "compute.c.h"
|
||||
#include "constantbuffer.c.h"
|
||||
#include "indexbuffer.c.h"
|
||||
#include "pipeline.c.h"
|
||||
#include "raytrace.c.h"
|
||||
#include "rendertarget.c.h"
|
||||
#include "sampler.c.h"
|
||||
#include "shader.c.h"
|
||||
#include "texture.c.h"
|
||||
#include "vertexbuffer.c.h"
|
||||
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/backend/graphics5/indexbuffer.h>
|
||||
#include <kinc/backend/graphics5/rendertarget.h>
|
||||
#include <kinc/backend/graphics5/texture.h>
|
||||
#include <kinc/backend/graphics5/vertexbuffer.h>
|
||||
@ -0,0 +1,130 @@
|
||||
#include "indexbuffer.h"
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
#include <kinc/graphics5/indexbuffer.h>
|
||||
|
||||
void kinc_g5_index_buffer_init(kinc_g5_index_buffer_t *buffer, int count, kinc_g5_index_buffer_format_t format, bool gpuMemory) {
|
||||
buffer->impl.count = count;
|
||||
buffer->impl.gpu_memory = gpuMemory;
|
||||
buffer->impl.format = format;
|
||||
|
||||
// static_assert(sizeof(D3D12IindexBufferView) == sizeof(D3D12_INDEX_BUFFER_VIEW), "Something is wrong with D3D12IindexBufferView");
|
||||
int uploadBufferSize = format == KINC_G5_INDEX_BUFFER_FORMAT_16BIT ? sizeof(uint16_t) * count : sizeof(uint32_t) * count;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProperties;
|
||||
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProperties.CreationNodeMask = 1;
|
||||
heapProperties.VisibleNodeMask = 1;
|
||||
|
||||
D3D12_RESOURCE_DESC resourceDesc;
|
||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resourceDesc.Alignment = 0;
|
||||
resourceDesc.Width = uploadBufferSize;
|
||||
resourceDesc.Height = 1;
|
||||
resourceDesc.DepthOrArraySize = 1;
|
||||
resourceDesc.MipLevels = 1;
|
||||
resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
resourceDesc.SampleDesc.Count = 1;
|
||||
resourceDesc.SampleDesc.Quality = 0;
|
||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
kinc_microsoft_affirm(device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&buffer->impl.upload_buffer)));
|
||||
|
||||
if (gpuMemory) {
|
||||
D3D12_HEAP_PROPERTIES heapProperties;
|
||||
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProperties.CreationNodeMask = 1;
|
||||
heapProperties.VisibleNodeMask = 1;
|
||||
|
||||
kinc_microsoft_affirm(device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&buffer->impl.index_buffer)));
|
||||
|
||||
buffer->impl.index_buffer_view.BufferLocation = buffer->impl.index_buffer->GetGPUVirtualAddress();
|
||||
}
|
||||
else {
|
||||
buffer->impl.index_buffer_view.BufferLocation = buffer->impl.upload_buffer->GetGPUVirtualAddress();
|
||||
}
|
||||
buffer->impl.index_buffer_view.SizeInBytes = uploadBufferSize;
|
||||
buffer->impl.index_buffer_view.Format = format == KINC_G5_INDEX_BUFFER_FORMAT_16BIT ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
|
||||
|
||||
buffer->impl.last_start = 0;
|
||||
buffer->impl.last_count = kinc_g5_index_buffer_count(buffer);
|
||||
}
|
||||
|
||||
void kinc_g5_index_buffer_destroy(kinc_g5_index_buffer_t *buffer) {
|
||||
if (buffer->impl.index_buffer != NULL) {
|
||||
buffer->impl.index_buffer->Release();
|
||||
buffer->impl.index_buffer = NULL;
|
||||
}
|
||||
|
||||
buffer->impl.upload_buffer->Release();
|
||||
buffer->impl.upload_buffer = NULL;
|
||||
}
|
||||
|
||||
static int kinc_g5_internal_index_buffer_stride(kinc_g5_index_buffer_t *buffer) {
|
||||
return buffer->impl.format == KINC_G5_INDEX_BUFFER_FORMAT_32BIT ? 4 : 2;
|
||||
}
|
||||
|
||||
void *kinc_g5_index_buffer_lock_all(kinc_g5_index_buffer_t *buffer) {
|
||||
return kinc_g5_index_buffer_lock(buffer, 0, kinc_g5_index_buffer_count(buffer));
|
||||
}
|
||||
|
||||
void *kinc_g5_index_buffer_lock(kinc_g5_index_buffer_t *buffer, int start, int count) {
|
||||
buffer->impl.last_start = start;
|
||||
buffer->impl.last_count = count;
|
||||
|
||||
D3D12_RANGE range;
|
||||
range.Begin = start * kinc_g5_internal_index_buffer_stride(buffer);
|
||||
range.End = (start + count) * kinc_g5_internal_index_buffer_stride(buffer);
|
||||
|
||||
void *p;
|
||||
buffer->impl.upload_buffer->Map(0, &range, &p);
|
||||
byte *bytes = (byte *)p;
|
||||
bytes += start * kinc_g5_internal_index_buffer_stride(buffer);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void kinc_g5_index_buffer_unlock_all(kinc_g5_index_buffer_t *buffer) {
|
||||
D3D12_RANGE range;
|
||||
range.Begin = buffer->impl.last_start * kinc_g5_internal_index_buffer_stride(buffer);
|
||||
range.End = (buffer->impl.last_start + buffer->impl.last_count) * kinc_g5_internal_index_buffer_stride(buffer);
|
||||
|
||||
buffer->impl.upload_buffer->Unmap(0, &range);
|
||||
}
|
||||
|
||||
void kinc_g5_index_buffer_unlock(kinc_g5_index_buffer_t *buffer, int count) {
|
||||
D3D12_RANGE range;
|
||||
range.Begin = buffer->impl.last_start * kinc_g5_internal_index_buffer_stride(buffer);
|
||||
range.End = (buffer->impl.last_start + count) * kinc_g5_internal_index_buffer_stride(buffer);
|
||||
|
||||
buffer->impl.upload_buffer->Unmap(0, &range);
|
||||
}
|
||||
|
||||
void kinc_g5_internal_index_buffer_upload(kinc_g5_index_buffer_t *buffer, ID3D12GraphicsCommandList *commandList) {
|
||||
if (!buffer->impl.gpu_memory)
|
||||
return;
|
||||
|
||||
commandList->CopyBufferRegion(buffer->impl.index_buffer, 0, buffer->impl.upload_buffer, 0,
|
||||
buffer->impl.format == KINC_G5_INDEX_BUFFER_FORMAT_16BIT ? sizeof(uint16_t) * buffer->impl.count
|
||||
: sizeof(uint32_t) * buffer->impl.count);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barriers[1] = {};
|
||||
barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barriers[0].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barriers[0].Transition.pResource = buffer->impl.index_buffer;
|
||||
barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_INDEX_BUFFER;
|
||||
barriers[0].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
|
||||
commandList->ResourceBarrier(1, barriers);
|
||||
}
|
||||
|
||||
int kinc_g5_index_buffer_count(kinc_g5_index_buffer_t *buffer) {
|
||||
return buffer->impl.count;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D12Resource;
|
||||
|
||||
struct D3D12IindexBufferView {
|
||||
__int64 BufferLocation;
|
||||
unsigned int SizeInBytes;
|
||||
int Format;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct ID3D12Resource *index_buffer;
|
||||
struct D3D12IindexBufferView index_buffer_view;
|
||||
struct ID3D12Resource *upload_buffer;
|
||||
int count;
|
||||
bool gpu_memory;
|
||||
int format;
|
||||
int last_start;
|
||||
int last_count;
|
||||
} IndexBuffer5Impl;
|
||||
|
||||
struct kinc_g5_index_buffer;
|
||||
|
||||
void kinc_g5_internal_index_buffer_upload(struct kinc_g5_index_buffer *buffer, struct ID3D12GraphicsCommandList *commandList);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,559 @@
|
||||
#include "pipeline.h"
|
||||
|
||||
#include <kinc/graphics5/graphics.h>
|
||||
#include <kinc/graphics5/pipeline.h>
|
||||
#include <kinc/graphics5/shader.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
void kinc_g5_internal_setConstants(kinc_g5_command_list_t *commandList, kinc_g5_pipeline_t *pipeline) {
|
||||
/*if (currentProgram->vertexShader->constantsSize > 0) {
|
||||
context->UpdateSubresource(currentProgram->vertexConstantBuffer, 0, nullptr, vertexConstants, 0, 0);
|
||||
context->VSSetConstantBuffers(0, 1, ¤tProgram->vertexConstantBuffer);
|
||||
}
|
||||
if (currentProgram->fragmentShader->constantsSize > 0) {
|
||||
context->UpdateSubresource(currentProgram->fragmentConstantBuffer, 0, nullptr, fragmentConstants, 0, 0);
|
||||
context->PSSetConstantBuffers(0, 1, ¤tProgram->fragmentConstantBuffer);
|
||||
}
|
||||
if (currentProgram->geometryShader != nullptr && currentProgram->geometryShader->constantsSize > 0) {
|
||||
context->UpdateSubresource(currentProgram->geometryConstantBuffer, 0, nullptr, geometryConstants, 0, 0);
|
||||
context->GSSetConstantBuffers(0, 1, ¤tProgram->geometryConstantBuffer);
|
||||
}
|
||||
if (currentProgram->tessControlShader != nullptr && currentProgram->tessControlShader->constantsSize > 0) {
|
||||
context->UpdateSubresource(currentProgram->tessControlConstantBuffer, 0, nullptr, tessControlConstants, 0, 0);
|
||||
context->HSSetConstantBuffers(0, 1, ¤tProgram->tessControlConstantBuffer);
|
||||
}
|
||||
if (currentProgram->tessEvalShader != nullptr && currentProgram->tessEvalShader->constantsSize > 0) {
|
||||
context->UpdateSubresource(currentProgram->tessEvalConstantBuffer, 0, nullptr, tessEvalConstants, 0, 0);
|
||||
context->DSSetConstantBuffers(0, 1, ¤tProgram->tessEvalConstantBuffer);
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef KINC_DXC
|
||||
// commandList->SetGraphicsRootSignature(pipeline->impl.rootSignature);
|
||||
commandList->impl._commandList->SetGraphicsRootSignature(globalRootSignature);
|
||||
#else
|
||||
commandList->impl._commandList->SetGraphicsRootSignature(globalRootSignature);
|
||||
#endif
|
||||
|
||||
if (pipeline->impl.textures > 0) {
|
||||
kinc_g5_internal_set_textures(commandList);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g5_internal_set_compute_constants(kinc_g5_command_list_t *commandList) {
|
||||
/*if (currentProgram->vertexShader->constantsSize > 0) {
|
||||
context->UpdateSubresource(currentProgram->vertexConstantBuffer, 0, nullptr, vertexConstants, 0, 0);
|
||||
context->VSSetConstantBuffers(0, 1, ¤tProgram->vertexConstantBuffer);
|
||||
}
|
||||
if (currentProgram->fragmentShader->constantsSize > 0) {
|
||||
context->UpdateSubresource(currentProgram->fragmentConstantBuffer, 0, nullptr, fragmentConstants, 0, 0);
|
||||
context->PSSetConstantBuffers(0, 1, ¤tProgram->fragmentConstantBuffer);
|
||||
}
|
||||
if (currentProgram->geometryShader != nullptr && currentProgram->geometryShader->constantsSize > 0) {
|
||||
context->UpdateSubresource(currentProgram->geometryConstantBuffer, 0, nullptr, geometryConstants, 0, 0);
|
||||
context->GSSetConstantBuffers(0, 1, ¤tProgram->geometryConstantBuffer);
|
||||
}
|
||||
if (currentProgram->tessControlShader != nullptr && currentProgram->tessControlShader->constantsSize > 0) {
|
||||
context->UpdateSubresource(currentProgram->tessControlConstantBuffer, 0, nullptr, tessControlConstants, 0, 0);
|
||||
context->HSSetConstantBuffers(0, 1, ¤tProgram->tessControlConstantBuffer);
|
||||
}
|
||||
if (currentProgram->tessEvalShader != nullptr && currentProgram->tessEvalShader->constantsSize > 0) {
|
||||
context->UpdateSubresource(currentProgram->tessEvalConstantBuffer, 0, nullptr, tessEvalConstants, 0, 0);
|
||||
context->DSSetConstantBuffers(0, 1, ¤tProgram->tessEvalConstantBuffer);
|
||||
}
|
||||
*/
|
||||
|
||||
commandList->impl._commandList->SetComputeRootSignature(globalComputeRootSignature);
|
||||
|
||||
// if (pipeline->impl.textures > 0) {
|
||||
kinc_g5_internal_set_textures(commandList);
|
||||
//}
|
||||
}
|
||||
|
||||
void kinc_g5_pipeline_init(kinc_g5_pipeline_t *pipe) {
|
||||
kinc_g5_internal_pipeline_init(pipe);
|
||||
}
|
||||
|
||||
void kinc_g5_pipeline_destroy(kinc_g5_pipeline_t *pipe) {
|
||||
if (pipe->impl.pso != NULL) {
|
||||
pipe->impl.pso->Release();
|
||||
pipe->impl.pso = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// void PipelineState5Impl::set(Graphics5::PipelineState* pipeline) {
|
||||
//_current = this;
|
||||
// context->VSSetShader((ID3D11VertexShader*)vertexShader->shader, nullptr, 0);
|
||||
// context->PSSetShader((ID3D11PixelShader*)fragmentShader->shader, nullptr, 0);
|
||||
|
||||
// if (geometryShader != nullptr) context->GSSetShader((ID3D11GeometryShader*)geometryShader->shader, nullptr, 0);
|
||||
// if (tessControlShader != nullptr) context->HSSetShader((ID3D11HullShader*)tessControlShader->shader, nullptr, 0);
|
||||
// if (tessEvalShader != nullptr) context->DSSetShader((ID3D11DomainShader*)tessEvalShader->shader, nullptr, 0);
|
||||
|
||||
// context->IASetInputLayout(inputLayout);
|
||||
//}
|
||||
|
||||
#define MAX_SHADER_THING 32
|
||||
|
||||
static ShaderConstant findConstant(kinc_g5_shader_t *shader, const char *name) {
|
||||
if (shader != NULL) {
|
||||
for (int i = 0; i < MAX_SHADER_THING; ++i) {
|
||||
if (strcmp(shader->impl.constants[i].name, name) == 0) {
|
||||
return shader->impl.constants[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShaderConstant constant;
|
||||
constant.name[0] = 0;
|
||||
constant.offset = -1;
|
||||
constant.size = 0;
|
||||
return constant;
|
||||
}
|
||||
|
||||
static ShaderTexture findTexture(kinc_g5_shader_t *shader, const char *name) {
|
||||
for (int i = 0; i < MAX_SHADER_THING; ++i) {
|
||||
if (strcmp(shader->impl.textures[i].name, name) == 0) {
|
||||
return shader->impl.textures[i];
|
||||
}
|
||||
}
|
||||
|
||||
ShaderTexture texture;
|
||||
texture.name[0] = 0;
|
||||
texture.texture = -1;
|
||||
return texture;
|
||||
}
|
||||
|
||||
static ShaderAttribute findAttribute(kinc_g5_shader_t *shader, const char *name) {
|
||||
for (int i = 0; i < MAX_SHADER_THING; ++i) {
|
||||
if (strcmp(shader->impl.attributes[i].name, name) == 0) {
|
||||
return shader->impl.attributes[i];
|
||||
}
|
||||
}
|
||||
|
||||
ShaderAttribute attribute;
|
||||
attribute.name[0] = 0;
|
||||
attribute.attribute = -1;
|
||||
return attribute;
|
||||
}
|
||||
|
||||
kinc_g5_constant_location_t kinc_g5_pipeline_get_constant_location(struct kinc_g5_pipeline *pipe, const char *name) {
|
||||
kinc_g5_constant_location_t location;
|
||||
|
||||
{
|
||||
ShaderConstant constant = findConstant(pipe->vertexShader, name);
|
||||
location.impl.vertexOffset = constant.offset;
|
||||
location.impl.vertexSize = constant.size;
|
||||
}
|
||||
|
||||
{
|
||||
ShaderConstant constant = findConstant(pipe->fragmentShader, name);
|
||||
location.impl.fragmentOffset = constant.offset;
|
||||
location.impl.fragmentSize = constant.size;
|
||||
}
|
||||
|
||||
location.impl.computeOffset = 0;
|
||||
location.impl.computeSize = 0;
|
||||
|
||||
{
|
||||
ShaderConstant constant = findConstant(pipe->geometryShader, name);
|
||||
location.impl.geometryOffset = constant.offset;
|
||||
location.impl.geometrySize = constant.size;
|
||||
}
|
||||
|
||||
{
|
||||
ShaderConstant constant = findConstant(pipe->tessellationControlShader, name);
|
||||
location.impl.tessControlOffset = constant.offset;
|
||||
location.impl.tessControlSize = constant.size;
|
||||
}
|
||||
|
||||
{
|
||||
ShaderConstant constant = findConstant(pipe->tessellationEvaluationShader, name);
|
||||
location.impl.tessEvalOffset = constant.offset;
|
||||
location.impl.tessEvalSize = constant.size;
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_g5_texture_unit_t kinc_g5_pipeline_get_texture_unit(kinc_g5_pipeline_t *pipe, const char *name) {
|
||||
kinc_g5_texture_unit_t unit;
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
unit.stages[i] = -1;
|
||||
}
|
||||
|
||||
ShaderTexture vertexTexture = findTexture(pipe->vertexShader, name);
|
||||
if (vertexTexture.texture != -1) {
|
||||
unit.stages[KINC_G5_SHADER_TYPE_VERTEX] = vertexTexture.texture;
|
||||
}
|
||||
else {
|
||||
ShaderTexture fragmentTexture = findTexture(pipe->fragmentShader, name);
|
||||
unit.stages[KINC_G5_SHADER_TYPE_FRAGMENT] = fragmentTexture.texture;
|
||||
}
|
||||
return unit;
|
||||
}
|
||||
|
||||
static D3D12_BLEND convert_blend_factor(kinc_g5_blending_factor_t factor) {
|
||||
switch (factor) {
|
||||
case KINC_G5_BLEND_ONE:
|
||||
return D3D12_BLEND_ONE;
|
||||
case KINC_G5_BLEND_ZERO:
|
||||
return D3D12_BLEND_ZERO;
|
||||
case KINC_G5_BLEND_SOURCE_ALPHA:
|
||||
return D3D12_BLEND_SRC_ALPHA;
|
||||
case KINC_G5_BLEND_DEST_ALPHA:
|
||||
return D3D12_BLEND_DEST_ALPHA;
|
||||
case KINC_G5_BLEND_INV_SOURCE_ALPHA:
|
||||
return D3D12_BLEND_INV_SRC_ALPHA;
|
||||
case KINC_G5_BLEND_INV_DEST_ALPHA:
|
||||
return D3D12_BLEND_INV_DEST_ALPHA;
|
||||
case KINC_G5_BLEND_SOURCE_COLOR:
|
||||
return D3D12_BLEND_SRC_COLOR;
|
||||
case KINC_G5_BLEND_DEST_COLOR:
|
||||
return D3D12_BLEND_DEST_COLOR;
|
||||
case KINC_G5_BLEND_INV_SOURCE_COLOR:
|
||||
return D3D12_BLEND_INV_SRC_COLOR;
|
||||
case KINC_G5_BLEND_INV_DEST_COLOR:
|
||||
return D3D12_BLEND_INV_DEST_COLOR;
|
||||
case KINC_G5_BLEND_CONSTANT:
|
||||
return D3D12_BLEND_BLEND_FACTOR;
|
||||
case KINC_G5_BLEND_INV_CONSTANT:
|
||||
return D3D12_BLEND_INV_BLEND_FACTOR;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D12_BLEND_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D12_BLEND_OP convert_blend_operation(kinc_g5_blending_operation_t op) {
|
||||
switch (op) {
|
||||
case KINC_G5_BLENDOP_ADD:
|
||||
return D3D12_BLEND_OP_ADD;
|
||||
case KINC_G5_BLENDOP_SUBTRACT:
|
||||
return D3D12_BLEND_OP_SUBTRACT;
|
||||
case KINC_G5_BLENDOP_REVERSE_SUBTRACT:
|
||||
return D3D12_BLEND_OP_REV_SUBTRACT;
|
||||
case KINC_G5_BLENDOP_MIN:
|
||||
return D3D12_BLEND_OP_MIN;
|
||||
case KINC_G5_BLENDOP_MAX:
|
||||
return D3D12_BLEND_OP_MAX;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D12_BLEND_OP_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D12_CULL_MODE convert_cull_mode(kinc_g5_cull_mode_t cullMode) {
|
||||
switch (cullMode) {
|
||||
case KINC_G5_CULL_MODE_CLOCKWISE:
|
||||
return D3D12_CULL_MODE_FRONT;
|
||||
case KINC_G5_CULL_MODE_COUNTERCLOCKWISE:
|
||||
return D3D12_CULL_MODE_BACK;
|
||||
case KINC_G5_CULL_MODE_NEVER:
|
||||
default:
|
||||
return D3D12_CULL_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D12_COMPARISON_FUNC convert_compare_mode(kinc_g5_compare_mode_t compare) {
|
||||
switch (compare) {
|
||||
default:
|
||||
case KINC_G5_COMPARE_MODE_ALWAYS:
|
||||
return D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
case KINC_G5_COMPARE_MODE_NEVER:
|
||||
return D3D12_COMPARISON_FUNC_NEVER;
|
||||
case KINC_G5_COMPARE_MODE_EQUAL:
|
||||
return D3D12_COMPARISON_FUNC_EQUAL;
|
||||
case KINC_G5_COMPARE_MODE_NOT_EQUAL:
|
||||
return D3D12_COMPARISON_FUNC_NOT_EQUAL;
|
||||
case KINC_G5_COMPARE_MODE_LESS:
|
||||
return D3D12_COMPARISON_FUNC_LESS;
|
||||
case KINC_G5_COMPARE_MODE_LESS_EQUAL:
|
||||
return D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
||||
case KINC_G5_COMPARE_MODE_GREATER:
|
||||
return D3D12_COMPARISON_FUNC_GREATER;
|
||||
case KINC_G5_COMPARE_MODE_GREATER_EQUAL:
|
||||
return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
|
||||
}
|
||||
}
|
||||
|
||||
static DXGI_FORMAT convert_format(kinc_g5_render_target_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
#ifdef KINC_WINDOWS
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
#else
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void set_blend_state(D3D12_BLEND_DESC *blend_desc, kinc_g5_pipeline_t *pipe, int target) {
|
||||
blend_desc->RenderTarget[target].BlendEnable = pipe->blend_source != KINC_G5_BLEND_ONE || pipe->blend_destination != KINC_G5_BLEND_ZERO ||
|
||||
pipe->alpha_blend_source != KINC_G5_BLEND_ONE || pipe->alpha_blend_destination != KINC_G5_BLEND_ZERO;
|
||||
blend_desc->RenderTarget[target].SrcBlend = convert_blend_factor(pipe->blend_source);
|
||||
blend_desc->RenderTarget[target].DestBlend = convert_blend_factor(pipe->blend_destination);
|
||||
blend_desc->RenderTarget[target].BlendOp = convert_blend_operation(pipe->blend_operation);
|
||||
blend_desc->RenderTarget[target].SrcBlendAlpha = convert_blend_factor(pipe->alpha_blend_source);
|
||||
blend_desc->RenderTarget[target].DestBlendAlpha = convert_blend_factor(pipe->alpha_blend_destination);
|
||||
blend_desc->RenderTarget[target].BlendOpAlpha = convert_blend_operation(pipe->alpha_blend_operation);
|
||||
blend_desc->RenderTarget[target].RenderTargetWriteMask =
|
||||
(((pipe->colorWriteMaskRed[target] ? D3D12_COLOR_WRITE_ENABLE_RED : 0) | (pipe->colorWriteMaskGreen[target] ? D3D12_COLOR_WRITE_ENABLE_GREEN : 0)) |
|
||||
(pipe->colorWriteMaskBlue[target] ? D3D12_COLOR_WRITE_ENABLE_BLUE : 0)) |
|
||||
(pipe->colorWriteMaskAlpha[target] ? D3D12_COLOR_WRITE_ENABLE_ALPHA : 0);
|
||||
}
|
||||
|
||||
void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipe) {
|
||||
// TODO FLOAT4x4
|
||||
int vertexAttributeCount = 0;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (pipe->inputLayout[i] == NULL) {
|
||||
break;
|
||||
}
|
||||
vertexAttributeCount += pipe->inputLayout[i]->size;
|
||||
}
|
||||
D3D12_INPUT_ELEMENT_DESC *vertexDesc = (D3D12_INPUT_ELEMENT_DESC *)alloca(sizeof(D3D12_INPUT_ELEMENT_DESC) * vertexAttributeCount);
|
||||
ZeroMemory(vertexDesc, sizeof(D3D12_INPUT_ELEMENT_DESC) * vertexAttributeCount);
|
||||
int curAttr = 0;
|
||||
for (int stream = 0; pipe->inputLayout[stream] != NULL; ++stream) {
|
||||
for (int i = 0; i < pipe->inputLayout[stream]->size; ++i) {
|
||||
vertexDesc[curAttr].SemanticName = "TEXCOORD";
|
||||
vertexDesc[curAttr].SemanticIndex = findAttribute(pipe->vertexShader, pipe->inputLayout[stream]->elements[i].name).attribute;
|
||||
vertexDesc[curAttr].InputSlot = stream;
|
||||
vertexDesc[curAttr].AlignedByteOffset = (i == 0) ? 0 : D3D12_APPEND_ALIGNED_ELEMENT;
|
||||
vertexDesc[curAttr].InputSlotClass =
|
||||
pipe->inputLayout[stream]->instanced ? D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA : D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
|
||||
vertexDesc[curAttr].InstanceDataStepRate = pipe->inputLayout[stream]->instanced ? 1 : 0;
|
||||
|
||||
switch (pipe->inputLayout[stream]->elements[i].data) {
|
||||
case KINC_G4_VERTEX_DATA_F32_1X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32_FLOAT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_2X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32G32_FLOAT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_3X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_1X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8_SINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_1X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8_UINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8_SNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8_UNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_2X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8G8_SINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_2X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8G8_UINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8G8_SNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8G8_UNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_4X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8G8B8A8_SINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8G8B8A8_UINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8G8B8A8_SNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_1X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16_SINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_1X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16_UINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16_SNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16_UNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16G16_SINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_2X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16G16_UINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16G16_SNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16G16_UNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16G16B16A16_SINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_4X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16G16B16A16_UINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16G16B16A16_SNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_1X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32_SINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_1X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32_UINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_2X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32G32_SINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_2X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32G32_UINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_3X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32G32B32_SINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_3X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32G32B32_UINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_4X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32G32B32A32_SINT;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_4X:
|
||||
vertexDesc[curAttr].Format = DXGI_FORMAT_R32G32B32A32_UINT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
curAttr++;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
#ifdef KINC_DXC
|
||||
// hr = device->CreateRootSignature(0, pipe->vertexShader->impl.data, pipe->vertexShader->impl.length, IID_GRAPHICS_PPV_ARGS(&pipe->impl.rootSignature));
|
||||
if (hr != S_OK) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not create root signature.");
|
||||
}
|
||||
pipe->impl.vertexConstantsSize = pipe->vertexShader->impl.constantsSize;
|
||||
pipe->impl.fragmentConstantsSize = pipe->fragmentShader->impl.constantsSize;
|
||||
#endif
|
||||
|
||||
pipe->impl.textures = pipe->fragmentShader->impl.texturesCount;
|
||||
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {0};
|
||||
psoDesc.VS.BytecodeLength = pipe->vertexShader->impl.length;
|
||||
psoDesc.VS.pShaderBytecode = pipe->vertexShader->impl.data;
|
||||
psoDesc.PS.BytecodeLength = pipe->fragmentShader->impl.length;
|
||||
psoDesc.PS.pShaderBytecode = pipe->fragmentShader->impl.data;
|
||||
#ifdef KINC_DXC
|
||||
// psoDesc.pRootSignature = pipe->impl.rootSignature;
|
||||
psoDesc.pRootSignature = globalRootSignature;
|
||||
#else
|
||||
psoDesc.pRootSignature = globalRootSignature;
|
||||
#endif
|
||||
psoDesc.NumRenderTargets = pipe->colorAttachmentCount;
|
||||
for (int i = 0; i < pipe->colorAttachmentCount; ++i) {
|
||||
psoDesc.RTVFormats[i] = convert_format(pipe->colorAttachment[i]);
|
||||
}
|
||||
psoDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
psoDesc.InputLayout.NumElements = vertexAttributeCount;
|
||||
psoDesc.InputLayout.pInputElementDescs = vertexDesc;
|
||||
|
||||
psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
psoDesc.RasterizerState.CullMode = convert_cull_mode(pipe->cullMode);
|
||||
psoDesc.RasterizerState.FrontCounterClockwise = FALSE;
|
||||
psoDesc.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
|
||||
psoDesc.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
|
||||
psoDesc.RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
|
||||
psoDesc.RasterizerState.DepthClipEnable = TRUE;
|
||||
psoDesc.RasterizerState.MultisampleEnable = FALSE;
|
||||
psoDesc.RasterizerState.AntialiasedLineEnable = FALSE;
|
||||
psoDesc.RasterizerState.ForcedSampleCount = 0;
|
||||
psoDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
|
||||
psoDesc.BlendState.AlphaToCoverageEnable = FALSE;
|
||||
psoDesc.BlendState.IndependentBlendEnable = FALSE;
|
||||
const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc = {
|
||||
FALSE,
|
||||
FALSE,
|
||||
D3D12_BLEND_ONE,
|
||||
D3D12_BLEND_ZERO,
|
||||
D3D12_BLEND_OP_ADD,
|
||||
D3D12_BLEND_ONE,
|
||||
D3D12_BLEND_ZERO,
|
||||
D3D12_BLEND_OP_ADD,
|
||||
D3D12_LOGIC_OP_NOOP,
|
||||
D3D12_COLOR_WRITE_ENABLE_ALL,
|
||||
};
|
||||
for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) {
|
||||
psoDesc.BlendState.RenderTarget[i] = defaultRenderTargetBlendDesc;
|
||||
}
|
||||
|
||||
bool independentBlend = false;
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
if (pipe->colorWriteMaskRed[0] != pipe->colorWriteMaskRed[i] || pipe->colorWriteMaskGreen[0] != pipe->colorWriteMaskGreen[i] ||
|
||||
pipe->colorWriteMaskBlue[0] != pipe->colorWriteMaskBlue[i] || pipe->colorWriteMaskAlpha[0] != pipe->colorWriteMaskAlpha[i]) {
|
||||
independentBlend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
set_blend_state(&psoDesc.BlendState, pipe, 0);
|
||||
if (independentBlend) {
|
||||
psoDesc.BlendState.IndependentBlendEnable = true;
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
set_blend_state(&psoDesc.BlendState, pipe, i);
|
||||
}
|
||||
}
|
||||
|
||||
psoDesc.DepthStencilState.DepthEnable = TRUE;
|
||||
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
||||
psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
|
||||
psoDesc.DepthStencilState.StencilEnable = FALSE;
|
||||
psoDesc.DepthStencilState.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
|
||||
psoDesc.DepthStencilState.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
|
||||
const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp = {D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS};
|
||||
psoDesc.DepthStencilState.FrontFace = defaultStencilOp;
|
||||
psoDesc.DepthStencilState.BackFace = defaultStencilOp;
|
||||
|
||||
psoDesc.DepthStencilState.DepthEnable = pipe->depthMode != KINC_G5_COMPARE_MODE_ALWAYS;
|
||||
psoDesc.DepthStencilState.DepthWriteMask = pipe->depthWrite ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
|
||||
psoDesc.DepthStencilState.DepthFunc = convert_compare_mode(pipe->depthMode);
|
||||
psoDesc.DepthStencilState.StencilEnable = false;
|
||||
psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT;
|
||||
psoDesc.SampleDesc.Count = 1;
|
||||
psoDesc.SampleMask = 0xFFFFFFFF;
|
||||
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
|
||||
hr = device->CreateGraphicsPipelineState(&psoDesc, IID_GRAPHICS_PPV_ARGS(&pipe->impl.pso));
|
||||
if (hr != S_OK) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not create pipeline.");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct kinc_g5_shader;
|
||||
|
||||
struct ID3D12PipelineState;
|
||||
struct ID3D12GraphicsCommandList;
|
||||
struct ID3D12RootSignature;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D12PipelineState *pso;
|
||||
#ifdef KINC_DXC
|
||||
// struct ID3D12RootSignature *rootSignature;
|
||||
int vertexConstantsSize;
|
||||
int fragmentConstantsSize;
|
||||
#endif
|
||||
int textures;
|
||||
// ID3D11InputLayout* inputLayout;
|
||||
// ID3D11Buffer* fragmentConstantBuffer;
|
||||
// ID3D11Buffer* vertexConstantBuffer;
|
||||
// ID3D11Buffer* geometryConstantBuffer;
|
||||
// ID3D11Buffer* tessEvalConstantBuffer;
|
||||
// ID3D11Buffer* tessControlConstantBuffer;
|
||||
|
||||
// static void setConstants(ID3D12GraphicsCommandList *commandList, Graphics5::PipelineState *pipeline);
|
||||
} PipelineState5Impl;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D12PipelineState *pso;
|
||||
#ifdef KINC_DXC
|
||||
struct ID3D12RootSignature *rootSignature;
|
||||
int vertexConstantsSize;
|
||||
int fragmentConstantsSize;
|
||||
#endif
|
||||
int textures;
|
||||
// ID3D11InputLayout* inputLayout;
|
||||
// ID3D11Buffer* fragmentConstantBuffer;
|
||||
// ID3D11Buffer* vertexConstantBuffer;
|
||||
// ID3D11Buffer* geometryConstantBuffer;
|
||||
// ID3D11Buffer* tessEvalConstantBuffer;
|
||||
// ID3D11Buffer* tessControlConstantBuffer;
|
||||
|
||||
// static void setConstants(ID3D12GraphicsCommandList *commandList, Graphics5::PipelineState *pipeline);
|
||||
} ComputePipelineState5Impl;
|
||||
|
||||
typedef struct {
|
||||
int vertexOffset;
|
||||
uint32_t vertexSize;
|
||||
int fragmentOffset;
|
||||
uint32_t fragmentSize;
|
||||
int computeOffset;
|
||||
uint32_t computeSize;
|
||||
int geometryOffset;
|
||||
uint32_t geometrySize;
|
||||
int tessEvalOffset;
|
||||
uint32_t tessEvalSize;
|
||||
int tessControlOffset;
|
||||
uint32_t tessControlSize;
|
||||
} ConstantLocation5Impl;
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} AttributeLocation5Impl;
|
||||
|
||||
struct kinc_g5_pipeline;
|
||||
struct kinc_g5_command_list;
|
||||
|
||||
void kinc_g5_internal_setConstants(struct kinc_g5_command_list *commandList, struct kinc_g5_pipeline *pipeline);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,486 @@
|
||||
#ifndef KINC_XBOX_ONE
|
||||
|
||||
#include <kinc/backend/graphics5/raytrace.h>
|
||||
|
||||
#include <kinc/graphics5/commandlist.h>
|
||||
#include <kinc/graphics5/constantbuffer.h>
|
||||
#include <kinc/graphics5/graphics.h>
|
||||
#include <kinc/graphics5/indexbuffer.h>
|
||||
#include <kinc/graphics5/raytrace.h>
|
||||
#include <kinc/graphics5/vertexbuffer.h>
|
||||
|
||||
static const wchar_t *hit_group_name = L"hitgroup";
|
||||
static const wchar_t *raygen_shader_name = L"raygeneration";
|
||||
static const wchar_t *closesthit_shader_name = L"closesthit";
|
||||
static const wchar_t *miss_shader_name = L"miss";
|
||||
|
||||
static ID3D12Device5 *dxrDevice;
|
||||
static ID3D12GraphicsCommandList4 *dxrCommandList;
|
||||
static ID3D12RootSignature *dxrRootSignature;
|
||||
static ID3D12DescriptorHeap *descriptorHeap;
|
||||
static kinc_raytrace_acceleration_structure_t *accel;
|
||||
static kinc_raytrace_pipeline_t *pipeline;
|
||||
static kinc_g5_texture_t *output = NULL;
|
||||
|
||||
void kinc_raytrace_pipeline_init(kinc_raytrace_pipeline_t *pipeline, kinc_g5_command_list_t *command_list, void *ray_shader, int ray_shader_size,
|
||||
kinc_g5_constant_buffer_t *constant_buffer) {
|
||||
pipeline->_constant_buffer = constant_buffer;
|
||||
// Descriptor heap
|
||||
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc;
|
||||
ZeroMemory(&descriptorHeapDesc, sizeof(descriptorHeapDesc));
|
||||
// Allocate a heap for 3 descriptors:
|
||||
// 2 - bottom and top level acceleration structure
|
||||
// 1 - raytracing output texture SRV
|
||||
descriptorHeapDesc.NumDescriptors = 3;
|
||||
descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
descriptorHeapDesc.NodeMask = 0;
|
||||
device->CreateDescriptorHeap(&descriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(&descriptorHeap));
|
||||
|
||||
// Device
|
||||
device->QueryInterface(IID_GRAPHICS_PPV_ARGS(&dxrDevice));
|
||||
command_list->impl._commandList->QueryInterface(IID_GRAPHICS_PPV_ARGS(&dxrCommandList));
|
||||
|
||||
// Root signatures
|
||||
// This is a root signature that is shared across all raytracing shaders invoked during a DispatchRays() call.
|
||||
D3D12_DESCRIPTOR_RANGE UAVDescriptor = {};
|
||||
UAVDescriptor.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
||||
UAVDescriptor.NumDescriptors = 1;
|
||||
UAVDescriptor.BaseShaderRegister = 0;
|
||||
UAVDescriptor.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||
|
||||
D3D12_ROOT_PARAMETER rootParameters[3] = {};
|
||||
// Output view
|
||||
rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
rootParameters[0].DescriptorTable.NumDescriptorRanges = 1;
|
||||
rootParameters[0].DescriptorTable.pDescriptorRanges = &UAVDescriptor;
|
||||
// Acceleration structure
|
||||
rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
||||
rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
rootParameters[1].Descriptor.ShaderRegister = 0;
|
||||
// Constant buffer
|
||||
rootParameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
||||
rootParameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
rootParameters[2].Descriptor.ShaderRegister = 0;
|
||||
|
||||
D3D12_ROOT_SIGNATURE_DESC dxrRootSignatureDesc = {0};
|
||||
dxrRootSignatureDesc.NumParameters = ARRAYSIZE(rootParameters);
|
||||
dxrRootSignatureDesc.pParameters = rootParameters;
|
||||
ID3DBlob *blob = NULL;
|
||||
ID3DBlob *error = NULL;
|
||||
D3D12SerializeRootSignature(&dxrRootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, &error);
|
||||
device->CreateRootSignature(1, blob->GetBufferPointer(), blob->GetBufferSize(), IID_GRAPHICS_PPV_ARGS(&dxrRootSignature));
|
||||
|
||||
// Pipeline
|
||||
D3D12_STATE_OBJECT_DESC raytracingPipeline;
|
||||
ZeroMemory(&raytracingPipeline, sizeof(raytracingPipeline));
|
||||
raytracingPipeline.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE;
|
||||
|
||||
D3D12_SHADER_BYTECODE shaderBytecode = {0};
|
||||
shaderBytecode.pShaderBytecode = ray_shader;
|
||||
shaderBytecode.BytecodeLength = ray_shader_size;
|
||||
|
||||
D3D12_DXIL_LIBRARY_DESC dxilLibrary = {0};
|
||||
dxilLibrary.DXILLibrary = shaderBytecode;
|
||||
D3D12_EXPORT_DESC exports[3] = {0};
|
||||
exports[0].Name = raygen_shader_name;
|
||||
exports[1].Name = closesthit_shader_name;
|
||||
exports[2].Name = miss_shader_name;
|
||||
dxilLibrary.pExports = exports;
|
||||
dxilLibrary.NumExports = 3;
|
||||
|
||||
D3D12_HIT_GROUP_DESC hitGroup = {0};
|
||||
hitGroup.ClosestHitShaderImport = closesthit_shader_name;
|
||||
hitGroup.HitGroupExport = hit_group_name;
|
||||
hitGroup.Type = D3D12_HIT_GROUP_TYPE_TRIANGLES;
|
||||
|
||||
D3D12_RAYTRACING_SHADER_CONFIG shaderConfig = {0};
|
||||
shaderConfig.MaxPayloadSizeInBytes = 4 * sizeof(float); // float4 color
|
||||
shaderConfig.MaxAttributeSizeInBytes = 2 * sizeof(float); // float2 barycentrics
|
||||
|
||||
D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = {0};
|
||||
pipelineConfig.MaxTraceRecursionDepth = 1; // ~ primary rays only
|
||||
|
||||
D3D12_STATE_SUBOBJECT subobjects[5] = {};
|
||||
subobjects[0].Type = D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY;
|
||||
subobjects[0].pDesc = &dxilLibrary;
|
||||
subobjects[1].Type = D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP;
|
||||
subobjects[1].pDesc = &hitGroup;
|
||||
subobjects[2].Type = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG;
|
||||
subobjects[2].pDesc = &shaderConfig;
|
||||
subobjects[3].Type = D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE;
|
||||
subobjects[3].pDesc = &dxrRootSignature;
|
||||
subobjects[4].Type = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG;
|
||||
subobjects[4].pDesc = &pipelineConfig;
|
||||
raytracingPipeline.NumSubobjects = 5;
|
||||
raytracingPipeline.pSubobjects = subobjects;
|
||||
|
||||
dxrDevice->CreateStateObject(&raytracingPipeline, IID_GRAPHICS_PPV_ARGS(&pipeline->impl.dxr_state));
|
||||
|
||||
// Shader tables
|
||||
// Get shader identifiers
|
||||
ID3D12StateObjectProperties *stateObjectProps = NULL;
|
||||
pipeline->impl.dxr_state->QueryInterface(IID_GRAPHICS_PPV_ARGS(&stateObjectProps));
|
||||
const void *rayGenShaderId = stateObjectProps->GetShaderIdentifier(raygen_shader_name);
|
||||
const void *missShaderId = stateObjectProps->GetShaderIdentifier(miss_shader_name);
|
||||
const void *hitGroupShaderId = stateObjectProps->GetShaderIdentifier(hit_group_name);
|
||||
UINT shaderIdSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES;
|
||||
int align = D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT;
|
||||
|
||||
// Ray gen shader table
|
||||
{
|
||||
UINT size = shaderIdSize + constant_buffer->impl.mySize;
|
||||
UINT shaderRecordSize = (size + (align - 1)) & ~(align - 1);
|
||||
D3D12_RESOURCE_DESC bufferDesc;
|
||||
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
|
||||
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
bufferDesc.Width = shaderRecordSize;
|
||||
bufferDesc.Height = 1;
|
||||
bufferDesc.DepthOrArraySize = 1;
|
||||
bufferDesc.MipLevels = 1;
|
||||
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
bufferDesc.SampleDesc.Count = 1;
|
||||
bufferDesc.SampleDesc.Quality = 0;
|
||||
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
D3D12_HEAP_PROPERTIES uploadHeapProperties;
|
||||
ZeroMemory(&uploadHeapProperties, sizeof(uploadHeapProperties));
|
||||
uploadHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
uploadHeapProperties.CreationNodeMask = 1;
|
||||
uploadHeapProperties.VisibleNodeMask = 1;
|
||||
|
||||
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&pipeline->impl.raygen_shader_table));
|
||||
|
||||
D3D12_RANGE rstRange = {0};
|
||||
rstRange.Begin = 0;
|
||||
rstRange.End = 0;
|
||||
uint8_t *byteDest;
|
||||
pipeline->impl.raygen_shader_table->Map(0, &rstRange, (void **)(&byteDest));
|
||||
|
||||
D3D12_RANGE cbRange = {0};
|
||||
cbRange.Begin = 0;
|
||||
cbRange.End = constant_buffer->impl.mySize;
|
||||
void *constantBufferData;
|
||||
constant_buffer->impl.constant_buffer->Map(0, &cbRange, (void **)&constantBufferData);
|
||||
memcpy(byteDest, rayGenShaderId, size);
|
||||
memcpy(byteDest + size, constantBufferData, constant_buffer->impl.mySize);
|
||||
pipeline->impl.raygen_shader_table->Unmap(0, NULL);
|
||||
}
|
||||
|
||||
// Miss shader table
|
||||
{
|
||||
UINT size = shaderIdSize;
|
||||
UINT shaderRecordSize = (size + (align - 1)) & ~(align - 1);
|
||||
D3D12_RESOURCE_DESC bufferDesc;
|
||||
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
|
||||
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
bufferDesc.Width = shaderRecordSize;
|
||||
bufferDesc.Height = 1;
|
||||
bufferDesc.DepthOrArraySize = 1;
|
||||
bufferDesc.MipLevels = 1;
|
||||
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
bufferDesc.SampleDesc.Count = 1;
|
||||
bufferDesc.SampleDesc.Quality = 0;
|
||||
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
D3D12_HEAP_PROPERTIES uploadHeapProperties;
|
||||
ZeroMemory(&uploadHeapProperties, sizeof(uploadHeapProperties));
|
||||
uploadHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
uploadHeapProperties.CreationNodeMask = 1;
|
||||
uploadHeapProperties.VisibleNodeMask = 1;
|
||||
|
||||
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&pipeline->impl.miss_shader_table));
|
||||
|
||||
D3D12_RANGE mstRange = {0};
|
||||
mstRange.Begin = 0;
|
||||
mstRange.End = 0;
|
||||
uint8_t *byteDest;
|
||||
pipeline->impl.miss_shader_table->Map(0, &mstRange, (void **)(&byteDest));
|
||||
memcpy(byteDest, missShaderId, size);
|
||||
pipeline->impl.miss_shader_table->Unmap(0, NULL);
|
||||
}
|
||||
|
||||
// Hit group shader table
|
||||
{
|
||||
UINT size = shaderIdSize;
|
||||
UINT shaderRecordSize = (size + (align - 1)) & ~(align - 1);
|
||||
D3D12_RESOURCE_DESC bufferDesc;
|
||||
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
|
||||
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
bufferDesc.Width = shaderRecordSize;
|
||||
bufferDesc.Height = 1;
|
||||
bufferDesc.DepthOrArraySize = 1;
|
||||
bufferDesc.MipLevels = 1;
|
||||
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
bufferDesc.SampleDesc.Count = 1;
|
||||
bufferDesc.SampleDesc.Quality = 0;
|
||||
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
D3D12_HEAP_PROPERTIES uploadHeapProperties;
|
||||
ZeroMemory(&uploadHeapProperties, sizeof(uploadHeapProperties));
|
||||
uploadHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
uploadHeapProperties.CreationNodeMask = 1;
|
||||
uploadHeapProperties.VisibleNodeMask = 1;
|
||||
|
||||
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&pipeline->impl.hitgroup_shader_table));
|
||||
|
||||
D3D12_RANGE hstRange = {0};
|
||||
hstRange.Begin = 0;
|
||||
hstRange.End = 0;
|
||||
uint8_t *byteDest;
|
||||
pipeline->impl.hitgroup_shader_table->Map(0, &hstRange, (void **)(&byteDest));
|
||||
memcpy(byteDest, hitGroupShaderId, size);
|
||||
pipeline->impl.hitgroup_shader_table->Unmap(0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_raytrace_pipeline_destroy(kinc_raytrace_pipeline_t *pipeline) {
|
||||
pipeline->impl.dxr_state->Release();
|
||||
pipeline->impl.raygen_shader_table->Release();
|
||||
pipeline->impl.miss_shader_table->Release();
|
||||
pipeline->impl.hitgroup_shader_table->Release();
|
||||
}
|
||||
|
||||
void kinc_raytrace_acceleration_structure_init(kinc_raytrace_acceleration_structure_t *accel, kinc_g5_command_list_t *command_list, kinc_g5_vertex_buffer_t *vb,
|
||||
kinc_g5_index_buffer_t *ib) {
|
||||
// Reset the command list for the acceleration structure construction
|
||||
command_list->impl._commandList->Reset(command_list->impl._commandAllocator, NULL);
|
||||
|
||||
D3D12_RAYTRACING_GEOMETRY_DESC geometryDesc = {};
|
||||
geometryDesc.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
|
||||
geometryDesc.Triangles.IndexBuffer = ib->impl.upload_buffer->GetGPUVirtualAddress();
|
||||
geometryDesc.Triangles.IndexCount = ib->impl.count;
|
||||
geometryDesc.Triangles.IndexFormat = ib->impl.format == KINC_G5_INDEX_BUFFER_FORMAT_16BIT ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
|
||||
geometryDesc.Triangles.Transform3x4 = 0;
|
||||
geometryDesc.Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
geometryDesc.Triangles.VertexCount = vb->impl.myCount;
|
||||
geometryDesc.Triangles.VertexBuffer.StartAddress = vb->impl.uploadBuffer->GetGPUVirtualAddress();
|
||||
geometryDesc.Triangles.VertexBuffer.StrideInBytes = vb->impl.uploadBuffer->GetDesc().Width / vb->impl.myCount;
|
||||
geometryDesc.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE;
|
||||
|
||||
// Get required sizes for an acceleration structure
|
||||
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS topLevelInputs = {};
|
||||
topLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
|
||||
topLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
|
||||
topLevelInputs.NumDescs = 1;
|
||||
topLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL;
|
||||
|
||||
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO topLevelPrebuildInfo = {0};
|
||||
dxrDevice->GetRaytracingAccelerationStructurePrebuildInfo(&topLevelInputs, &topLevelPrebuildInfo);
|
||||
|
||||
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO bottomLevelPrebuildInfo = {0};
|
||||
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS bottomLevelInputs = topLevelInputs;
|
||||
bottomLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL;
|
||||
bottomLevelInputs.pGeometryDescs = &geometryDesc;
|
||||
bottomLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
|
||||
dxrDevice->GetRaytracingAccelerationStructurePrebuildInfo(&bottomLevelInputs, &bottomLevelPrebuildInfo);
|
||||
|
||||
ID3D12Resource *scratchResource;
|
||||
{
|
||||
UINT64 tlSize = topLevelPrebuildInfo.ScratchDataSizeInBytes;
|
||||
UINT64 blSize = bottomLevelPrebuildInfo.ScratchDataSizeInBytes;
|
||||
D3D12_RESOURCE_DESC bufferDesc;
|
||||
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
|
||||
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
bufferDesc.Width = tlSize > blSize ? tlSize : blSize;
|
||||
bufferDesc.Height = 1;
|
||||
bufferDesc.DepthOrArraySize = 1;
|
||||
bufferDesc.MipLevels = 1;
|
||||
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
bufferDesc.SampleDesc.Count = 1;
|
||||
bufferDesc.SampleDesc.Quality = 0;
|
||||
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
bufferDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
D3D12_HEAP_PROPERTIES uploadHeapProperties;
|
||||
ZeroMemory(&uploadHeapProperties, sizeof(uploadHeapProperties));
|
||||
uploadHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
uploadHeapProperties.CreationNodeMask = 1;
|
||||
uploadHeapProperties.VisibleNodeMask = 1;
|
||||
|
||||
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&scratchResource));
|
||||
}
|
||||
|
||||
// Allocate resources for acceleration structures
|
||||
// The resources that will contain acceleration structures must be created in the state D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE,
|
||||
// and must have resource flag D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS.
|
||||
{
|
||||
D3D12_RESOURCE_DESC bufferDesc = {};
|
||||
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
bufferDesc.Width = bottomLevelPrebuildInfo.ResultDataMaxSizeInBytes;
|
||||
bufferDesc.Height = 1;
|
||||
bufferDesc.DepthOrArraySize = 1;
|
||||
bufferDesc.MipLevels = 1;
|
||||
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
bufferDesc.SampleDesc.Count = 1;
|
||||
bufferDesc.SampleDesc.Quality = 0;
|
||||
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
bufferDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
D3D12_HEAP_PROPERTIES uploadHeapProperties = {};
|
||||
uploadHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
uploadHeapProperties.CreationNodeMask = 1;
|
||||
uploadHeapProperties.VisibleNodeMask = 1;
|
||||
|
||||
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&accel->impl.bottom_level_accel));
|
||||
}
|
||||
{
|
||||
D3D12_RESOURCE_DESC bufferDesc = {};
|
||||
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
bufferDesc.Width = topLevelPrebuildInfo.ResultDataMaxSizeInBytes;
|
||||
bufferDesc.Height = 1;
|
||||
bufferDesc.DepthOrArraySize = 1;
|
||||
bufferDesc.MipLevels = 1;
|
||||
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
bufferDesc.SampleDesc.Count = 1;
|
||||
bufferDesc.SampleDesc.Quality = 0;
|
||||
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
bufferDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
D3D12_HEAP_PROPERTIES uploadHeapProperties = {};
|
||||
uploadHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
uploadHeapProperties.CreationNodeMask = 1;
|
||||
uploadHeapProperties.VisibleNodeMask = 1;
|
||||
|
||||
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&accel->impl.top_level_accel));
|
||||
}
|
||||
|
||||
// Create an instance desc for the bottom-level acceleration structure
|
||||
ID3D12Resource *instanceDescs;
|
||||
D3D12_RAYTRACING_INSTANCE_DESC instanceDesc = {0};
|
||||
instanceDesc.Transform[0][0] = instanceDesc.Transform[1][1] = instanceDesc.Transform[2][2] = 1;
|
||||
instanceDesc.InstanceMask = 1;
|
||||
instanceDesc.AccelerationStructure = accel->impl.bottom_level_accel->GetGPUVirtualAddress();
|
||||
|
||||
D3D12_RESOURCE_DESC bufferDesc;
|
||||
ZeroMemory(&bufferDesc, sizeof(bufferDesc));
|
||||
bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
bufferDesc.Width = sizeof(instanceDesc);
|
||||
bufferDesc.Height = 1;
|
||||
bufferDesc.DepthOrArraySize = 1;
|
||||
bufferDesc.MipLevels = 1;
|
||||
bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
bufferDesc.SampleDesc.Count = 1;
|
||||
bufferDesc.SampleDesc.Quality = 0;
|
||||
bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
D3D12_HEAP_PROPERTIES uploadHeapProperties = {};
|
||||
uploadHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
uploadHeapProperties.CreationNodeMask = 1;
|
||||
uploadHeapProperties.VisibleNodeMask = 1;
|
||||
|
||||
device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&instanceDescs));
|
||||
void *mappedData;
|
||||
instanceDescs->Map(0, NULL, &mappedData);
|
||||
memcpy(mappedData, &instanceDesc, sizeof(instanceDesc));
|
||||
instanceDescs->Unmap(0, NULL);
|
||||
|
||||
// Bottom Level Acceleration Structure desc
|
||||
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC bottomLevelBuildDesc = {0};
|
||||
bottomLevelBuildDesc.Inputs = bottomLevelInputs;
|
||||
bottomLevelBuildDesc.ScratchAccelerationStructureData = scratchResource->GetGPUVirtualAddress();
|
||||
bottomLevelBuildDesc.DestAccelerationStructureData = accel->impl.bottom_level_accel->GetGPUVirtualAddress();
|
||||
|
||||
// Top Level Acceleration Structure desc
|
||||
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC topLevelBuildDesc = bottomLevelBuildDesc;
|
||||
topLevelInputs.InstanceDescs = instanceDescs->GetGPUVirtualAddress();
|
||||
topLevelBuildDesc.Inputs = topLevelInputs;
|
||||
topLevelBuildDesc.DestAccelerationStructureData = accel->impl.top_level_accel->GetGPUVirtualAddress();
|
||||
topLevelBuildDesc.ScratchAccelerationStructureData = scratchResource->GetGPUVirtualAddress();
|
||||
|
||||
// Build acceleration structure
|
||||
dxrCommandList->BuildRaytracingAccelerationStructure(&bottomLevelBuildDesc, 0, NULL);
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
|
||||
barrier.UAV.pResource = accel->impl.bottom_level_accel;
|
||||
command_list->impl._commandList->ResourceBarrier(1, &barrier);
|
||||
dxrCommandList->BuildRaytracingAccelerationStructure(&topLevelBuildDesc, 0, NULL);
|
||||
|
||||
kinc_g5_command_list_end(command_list);
|
||||
kinc_g5_command_list_execute(command_list);
|
||||
kinc_g5_command_list_wait_for_execution_to_finish(command_list);
|
||||
kinc_g5_command_list_begin(command_list);
|
||||
}
|
||||
|
||||
void kinc_raytrace_acceleration_structure_destroy(kinc_raytrace_acceleration_structure_t *accel) {
|
||||
accel->impl.bottom_level_accel->Release();
|
||||
accel->impl.top_level_accel->Release();
|
||||
}
|
||||
|
||||
void kinc_raytrace_set_acceleration_structure(kinc_raytrace_acceleration_structure_t *_accel) {
|
||||
accel = _accel;
|
||||
}
|
||||
|
||||
void kinc_raytrace_set_pipeline(kinc_raytrace_pipeline_t *_pipeline) {
|
||||
pipeline = _pipeline;
|
||||
}
|
||||
|
||||
void kinc_raytrace_set_target(kinc_g5_texture_t *_output) {
|
||||
if (_output != output) {
|
||||
output = _output;
|
||||
|
||||
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
|
||||
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
|
||||
device->CreateUnorderedAccessView(output->impl.image, NULL, &uavDesc, descriptorHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_raytrace_dispatch_rays(kinc_g5_command_list_t *command_list) {
|
||||
command_list->impl._commandList->SetComputeRootSignature(dxrRootSignature);
|
||||
|
||||
// Bind the heaps, acceleration structure and dispatch rays
|
||||
command_list->impl._commandList->SetDescriptorHeaps(1, &descriptorHeap);
|
||||
command_list->impl._commandList->SetComputeRootDescriptorTable(0, descriptorHeap->GetGPUDescriptorHandleForHeapStart());
|
||||
command_list->impl._commandList->SetComputeRootShaderResourceView(1, accel->impl.top_level_accel->GetGPUVirtualAddress());
|
||||
D3D12_GPU_VIRTUAL_ADDRESS cbGpuAddress = pipeline->_constant_buffer->impl.constant_buffer->GetGPUVirtualAddress();
|
||||
command_list->impl._commandList->SetComputeRootConstantBufferView(2, cbGpuAddress);
|
||||
|
||||
// Since each shader table has only one shader record, the stride is same as the size.
|
||||
D3D12_DISPATCH_RAYS_DESC dispatchDesc = {0};
|
||||
dispatchDesc.HitGroupTable.StartAddress = pipeline->impl.hitgroup_shader_table->GetGPUVirtualAddress();
|
||||
dispatchDesc.HitGroupTable.SizeInBytes = pipeline->impl.hitgroup_shader_table->GetDesc().Width;
|
||||
dispatchDesc.HitGroupTable.StrideInBytes = dispatchDesc.HitGroupTable.SizeInBytes;
|
||||
dispatchDesc.MissShaderTable.StartAddress = pipeline->impl.miss_shader_table->GetGPUVirtualAddress();
|
||||
dispatchDesc.MissShaderTable.SizeInBytes = pipeline->impl.miss_shader_table->GetDesc().Width;
|
||||
dispatchDesc.MissShaderTable.StrideInBytes = dispatchDesc.MissShaderTable.SizeInBytes;
|
||||
dispatchDesc.RayGenerationShaderRecord.StartAddress = pipeline->impl.raygen_shader_table->GetGPUVirtualAddress();
|
||||
dispatchDesc.RayGenerationShaderRecord.SizeInBytes = pipeline->impl.raygen_shader_table->GetDesc().Width;
|
||||
dispatchDesc.Width = output->texWidth;
|
||||
dispatchDesc.Height = output->texHeight;
|
||||
dispatchDesc.Depth = 1;
|
||||
dxrCommandList->SetPipelineState1(pipeline->impl.dxr_state);
|
||||
dxrCommandList->DispatchRays(&dispatchDesc);
|
||||
}
|
||||
|
||||
void kinc_raytrace_copy(kinc_g5_command_list_t *command_list, kinc_g5_render_target_t *target, kinc_g5_texture_t *source) {
|
||||
D3D12_RESOURCE_BARRIER preCopyBarriers[2] = {};
|
||||
preCopyBarriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
preCopyBarriers[0].Transition.pResource = target->impl.renderTarget;
|
||||
preCopyBarriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
preCopyBarriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
preCopyBarriers[0].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
preCopyBarriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
preCopyBarriers[1].Transition.pResource = source->impl.image;
|
||||
preCopyBarriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
preCopyBarriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
preCopyBarriers[1].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
command_list->impl._commandList->ResourceBarrier(ARRAYSIZE(preCopyBarriers), preCopyBarriers);
|
||||
|
||||
command_list->impl._commandList->CopyResource(target->impl.renderTarget, source->impl.image);
|
||||
|
||||
D3D12_RESOURCE_BARRIER postCopyBarriers[2] = {};
|
||||
postCopyBarriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
postCopyBarriers[0].Transition.pResource = target->impl.renderTarget;
|
||||
postCopyBarriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
postCopyBarriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||
postCopyBarriers[0].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
postCopyBarriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
postCopyBarriers[1].Transition.pResource = source->impl.image;
|
||||
postCopyBarriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
postCopyBarriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
postCopyBarriers[1].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
command_list->impl._commandList->ResourceBarrier(ARRAYSIZE(postCopyBarriers), postCopyBarriers);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D12StateObject;
|
||||
struct ID3D12Resource;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D12StateObject *dxr_state;
|
||||
struct ID3D12Resource *raygen_shader_table;
|
||||
struct ID3D12Resource *miss_shader_table;
|
||||
struct ID3D12Resource *hitgroup_shader_table;
|
||||
} kinc_raytrace_pipeline_impl_t;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D12Resource *bottom_level_accel;
|
||||
struct ID3D12Resource *top_level_accel;
|
||||
} kinc_raytrace_acceleration_structure_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,287 @@
|
||||
#include "rendertarget.h"
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
#include <kinc/graphics5/rendertarget.h>
|
||||
#include <kinc/graphics5/texture.h>
|
||||
|
||||
#ifdef KINC_WINDOWS
|
||||
#include <dxgi1_4.h>
|
||||
#endif
|
||||
|
||||
#ifdef KINC_DIRECT3D_HAS_NO_SWAPCHAIN
|
||||
extern ID3D12Resource *swapChainRenderTargets[KINC_INTERNAL_D3D12_SWAP_CHAIN_COUNT];
|
||||
#endif
|
||||
|
||||
static void WaitForFence(ID3D12Fence *fence, UINT64 completionValue, HANDLE waitEvent) {
|
||||
if (fence->GetCompletedValue() < completionValue) {
|
||||
fence->SetEventOnCompletion(completionValue, waitEvent);
|
||||
WaitForSingleObject(waitEvent, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
static void createRenderTargetView(ID3D12Resource *renderTarget, ID3D12DescriptorHeap *renderTargetDescriptorHeap, DXGI_FORMAT format) {
|
||||
// const D3D12_RESOURCE_DESC resourceDesc = renderTarget->lpVtbl->GetDesc(renderTarget);
|
||||
|
||||
D3D12_RENDER_TARGET_VIEW_DESC viewDesc;
|
||||
viewDesc.Format = format;
|
||||
viewDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
viewDesc.Texture2D.MipSlice = 0;
|
||||
viewDesc.Texture2D.PlaneSlice = 0;
|
||||
|
||||
device->CreateRenderTargetView(renderTarget, &viewDesc, renderTargetDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
}
|
||||
|
||||
static DXGI_FORMAT convertFormat(kinc_g5_render_target_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case KINC_G5_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
#ifdef KINC_WINDOWS
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
#else
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void kinc_memory_emergency();
|
||||
|
||||
static void render_target_init(kinc_g5_render_target_t *render_target, int width, int height, kinc_g5_render_target_format_t format, int depthBufferBits,
|
||||
int stencilBufferBits, int samples_per_pixel, int framebuffer_index) {
|
||||
render_target->texWidth = render_target->width = width;
|
||||
render_target->texHeight = render_target->height = height;
|
||||
render_target->impl.stage = 0;
|
||||
render_target->impl.stage_depth = -1;
|
||||
render_target->impl.renderTargetReadback = NULL;
|
||||
render_target->impl.framebuffer_index = framebuffer_index;
|
||||
|
||||
DXGI_FORMAT dxgiFormat = convertFormat(format);
|
||||
|
||||
D3D12_CLEAR_VALUE clearValue;
|
||||
clearValue.Format = dxgiFormat;
|
||||
clearValue.Color[0] = 0.0f;
|
||||
clearValue.Color[1] = 0.0f;
|
||||
clearValue.Color[2] = 0.0f;
|
||||
clearValue.Color[3] = 1.0f;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProperties;
|
||||
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProperties.CreationNodeMask = 1;
|
||||
heapProperties.VisibleNodeMask = 1;
|
||||
|
||||
D3D12_RESOURCE_DESC texResourceDesc;
|
||||
texResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
texResourceDesc.Alignment = 0;
|
||||
texResourceDesc.Width = render_target->texWidth;
|
||||
texResourceDesc.Height = render_target->texHeight;
|
||||
texResourceDesc.DepthOrArraySize = 1;
|
||||
texResourceDesc.MipLevels = 1;
|
||||
texResourceDesc.Format = dxgiFormat;
|
||||
texResourceDesc.SampleDesc.Count = 1;
|
||||
texResourceDesc.SampleDesc.Quality = 0;
|
||||
texResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
texResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
|
||||
heapDesc.NumDescriptors = 1;
|
||||
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
kinc_microsoft_affirm(device->CreateDescriptorHeap(&heapDesc, IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTargetDescriptorHeap)));
|
||||
|
||||
if (framebuffer_index >= 0) {
|
||||
#ifdef KINC_DIRECT3D_HAS_NO_SWAPCHAIN
|
||||
render_target->impl.renderTarget = swapChainRenderTargets[framebuffer_index];
|
||||
#else
|
||||
IDXGISwapChain *swapChain = kinc_dx_current_window()->swapChain;
|
||||
kinc_microsoft_affirm(swapChain->GetBuffer(framebuffer_index, IID_PPV_ARGS(&render_target->impl.renderTarget)));
|
||||
wchar_t buffer[128];
|
||||
wsprintf(buffer, L"Backbuffer (index %i)", framebuffer_index);
|
||||
render_target->impl.renderTarget->SetName(buffer);
|
||||
#endif
|
||||
createRenderTargetView(render_target->impl.renderTarget, render_target->impl.renderTargetDescriptorHeap, dxgiFormat);
|
||||
}
|
||||
else {
|
||||
HRESULT result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &texResourceDesc, D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
&clearValue, IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTarget));
|
||||
if (result != S_OK) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
kinc_memory_emergency();
|
||||
result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &texResourceDesc, D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
&clearValue, IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTarget));
|
||||
if (result == S_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_RENDER_TARGET_VIEW_DESC view;
|
||||
// const D3D12_RESOURCE_DESC resourceDesc = render_target->impl.renderTarget->lpVtbl->GetDesc(render_target->impl.renderTarget);
|
||||
view.Format = dxgiFormat;
|
||||
view.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
view.Texture2D.MipSlice = 0;
|
||||
view.Texture2D.PlaneSlice = 0;
|
||||
|
||||
device->CreateRenderTargetView(render_target->impl.renderTarget, &view,
|
||||
render_target->impl.renderTargetDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
}
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {};
|
||||
descriptorHeapDesc.NumDescriptors = 1;
|
||||
|
||||
descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
descriptorHeapDesc.NodeMask = 0;
|
||||
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
|
||||
kinc_microsoft_affirm(device->CreateDescriptorHeap(&descriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(&render_target->impl.srvDescriptorHeap)));
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
|
||||
ZeroMemory(&shaderResourceViewDesc, sizeof(shaderResourceViewDesc));
|
||||
shaderResourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderResourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
shaderResourceViewDesc.Format = dxgiFormat;
|
||||
shaderResourceViewDesc.Texture2D.MipLevels = 1;
|
||||
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||
|
||||
device->CreateShaderResourceView(render_target->impl.renderTarget, &shaderResourceViewDesc,
|
||||
render_target->impl.srvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
|
||||
dsvHeapDesc.NumDescriptors = 1;
|
||||
dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
|
||||
dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
kinc_microsoft_affirm(device->CreateDescriptorHeap(&dsvHeapDesc, IID_GRAPHICS_PPV_ARGS(&render_target->impl.depthStencilDescriptorHeap)));
|
||||
|
||||
D3D12_RESOURCE_DESC depthTexture;
|
||||
depthTexture.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
depthTexture.Alignment = 0;
|
||||
depthTexture.Width = width;
|
||||
depthTexture.Height = height;
|
||||
depthTexture.DepthOrArraySize = 1;
|
||||
depthTexture.MipLevels = 1;
|
||||
depthTexture.Format = DXGI_FORMAT_D32_FLOAT;
|
||||
depthTexture.SampleDesc.Count = 1;
|
||||
depthTexture.SampleDesc.Quality = 0;
|
||||
depthTexture.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
depthTexture.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||
|
||||
D3D12_CLEAR_VALUE clearValue;
|
||||
clearValue.Format = DXGI_FORMAT_D32_FLOAT;
|
||||
clearValue.DepthStencil.Depth = 1.0f;
|
||||
clearValue.DepthStencil.Stencil = 0;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProperties;
|
||||
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProperties.CreationNodeMask = 1;
|
||||
heapProperties.VisibleNodeMask = 1;
|
||||
|
||||
HRESULT result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &depthTexture, D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue,
|
||||
IID_GRAPHICS_PPV_ARGS(&render_target->impl.depthStencilTexture));
|
||||
if (result != S_OK) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
kinc_memory_emergency();
|
||||
result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &depthTexture, D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue,
|
||||
IID_GRAPHICS_PPV_ARGS(&render_target->impl.depthStencilTexture));
|
||||
if (result == S_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
device->CreateDepthStencilView(render_target->impl.depthStencilTexture, NULL,
|
||||
render_target->impl.depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
|
||||
// Reading depth texture as a shader resource
|
||||
D3D12_DESCRIPTOR_HEAP_DESC srvDepthHeapDesc = {};
|
||||
srvDepthHeapDesc.NumDescriptors = 1;
|
||||
srvDepthHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
srvDepthHeapDesc.NodeMask = 0;
|
||||
srvDepthHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
kinc_microsoft_affirm(device->CreateDescriptorHeap(&srvDepthHeapDesc, IID_GRAPHICS_PPV_ARGS(&render_target->impl.srvDepthDescriptorHeap)));
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDepthViewDesc;
|
||||
ZeroMemory(&srvDepthViewDesc, sizeof(srvDepthViewDesc));
|
||||
srvDepthViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDepthViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
srvDepthViewDesc.Format = DXGI_FORMAT_R32_FLOAT;
|
||||
srvDepthViewDesc.Texture2D.MipLevels = 1;
|
||||
srvDepthViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
srvDepthViewDesc.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||
device->CreateShaderResourceView(render_target->impl.depthStencilTexture, &srvDepthViewDesc,
|
||||
render_target->impl.srvDepthDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
}
|
||||
else {
|
||||
render_target->impl.depthStencilDescriptorHeap = NULL;
|
||||
render_target->impl.depthStencilTexture = NULL;
|
||||
render_target->impl.srvDepthDescriptorHeap = NULL;
|
||||
}
|
||||
|
||||
render_target->impl.scissor.top = 0;
|
||||
render_target->impl.scissor.left = 0;
|
||||
render_target->impl.scissor.right = width;
|
||||
render_target->impl.scissor.bottom = height;
|
||||
|
||||
render_target->impl.viewport.TopLeftX = 0.0f;
|
||||
render_target->impl.viewport.TopLeftY = 0.0f;
|
||||
render_target->impl.viewport.Width = (float)width;
|
||||
render_target->impl.viewport.Height = (float)height;
|
||||
render_target->impl.viewport.MinDepth = 0.0f;
|
||||
render_target->impl.viewport.MaxDepth = 1.0f;
|
||||
}
|
||||
|
||||
void kinc_g5_render_target_init_with_multisampling(kinc_g5_render_target_t *target, int width, int height, kinc_g5_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
render_target_init(target, width, height, format, depthBufferBits, stencilBufferBits, samples_per_pixel, -1);
|
||||
}
|
||||
|
||||
static int framebuffer_count = 0;
|
||||
|
||||
void kinc_g5_render_target_init_framebuffer_with_multisampling(kinc_g5_render_target_t *target, int width, int height, kinc_g5_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
render_target_init(target, width, height, format, depthBufferBits, stencilBufferBits, samples_per_pixel, framebuffer_count);
|
||||
framebuffer_count += 1;
|
||||
}
|
||||
|
||||
void kinc_g5_render_target_init_cube_with_multisampling(kinc_g5_render_target_t *render_target, int cubeMapSize, kinc_g5_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
render_target->impl.stage = 0;
|
||||
render_target->impl.stage_depth = -1;
|
||||
}
|
||||
|
||||
void kinc_g5_render_target_destroy(kinc_g5_render_target_t *render_target) {
|
||||
if (render_target->impl.framebuffer_index >= 0) {
|
||||
framebuffer_count -= 1;
|
||||
}
|
||||
|
||||
render_target->impl.renderTarget->Release();
|
||||
render_target->impl.renderTargetDescriptorHeap->Release();
|
||||
render_target->impl.srvDescriptorHeap->Release();
|
||||
if (render_target->impl.depthStencilTexture != NULL) {
|
||||
render_target->impl.depthStencilTexture->Release();
|
||||
render_target->impl.depthStencilDescriptorHeap->Release();
|
||||
render_target->impl.srvDepthDescriptorHeap->Release();
|
||||
}
|
||||
if (render_target->impl.renderTargetReadback != NULL) {
|
||||
render_target->impl.renderTargetReadback->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g5_render_target_set_depth_stencil_from(kinc_g5_render_target_t *render_target, kinc_g5_render_target_t *source) {
|
||||
render_target->impl.depthStencilDescriptorHeap = source->impl.depthStencilDescriptorHeap;
|
||||
render_target->impl.srvDepthDescriptorHeap = source->impl.srvDepthDescriptorHeap;
|
||||
render_target->impl.depthStencilTexture = source->impl.depthStencilTexture;
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "d3d12mini.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum RenderTargetResourceState { RenderTargetResourceStateUndefined, RenderTargetResourceStateRenderTarget, RenderTargetResourceStateTexture };
|
||||
|
||||
typedef struct {
|
||||
struct ID3D12Resource *renderTarget;
|
||||
struct ID3D12Resource *renderTargetReadback;
|
||||
struct ID3D12DescriptorHeap *renderTargetDescriptorHeap;
|
||||
struct ID3D12DescriptorHeap *srvDescriptorHeap;
|
||||
struct ID3D12DescriptorHeap *depthStencilDescriptorHeap;
|
||||
struct ID3D12DescriptorHeap *srvDepthDescriptorHeap;
|
||||
struct ID3D12Resource *depthStencilTexture;
|
||||
struct D3D12Viewport viewport;
|
||||
struct D3D12Rect scissor;
|
||||
int stage;
|
||||
int stage_depth;
|
||||
int framebuffer_index;
|
||||
} RenderTarget5Impl;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,145 @@
|
||||
#include <kinc/graphics5/sampler.h>
|
||||
|
||||
static D3D12_TEXTURE_ADDRESS_MODE convert_texture_addressing(kinc_g5_texture_addressing_t addressing) {
|
||||
switch (addressing) {
|
||||
case KINC_G5_TEXTURE_ADDRESSING_REPEAT:
|
||||
return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
case KINC_G5_TEXTURE_ADDRESSING_MIRROR:
|
||||
return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
|
||||
case KINC_G5_TEXTURE_ADDRESSING_CLAMP:
|
||||
return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
case KINC_G5_TEXTURE_ADDRESSING_BORDER:
|
||||
return D3D12_TEXTURE_ADDRESS_MODE_BORDER;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D12_FILTER convert_filter(kinc_g5_texture_filter_t minification, kinc_g5_texture_filter_t magnification, kinc_g5_mipmap_filter_t mipmap) {
|
||||
switch (minification) {
|
||||
case KINC_G5_TEXTURE_FILTER_POINT:
|
||||
switch (magnification) {
|
||||
case KINC_G5_TEXTURE_FILTER_POINT:
|
||||
switch (mipmap) {
|
||||
case KINC_G5_MIPMAP_FILTER_NONE:
|
||||
case KINC_G5_MIPMAP_FILTER_POINT:
|
||||
return D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
case KINC_G5_MIPMAP_FILTER_LINEAR:
|
||||
return D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_LINEAR:
|
||||
switch (mipmap) {
|
||||
case KINC_G5_MIPMAP_FILTER_NONE:
|
||||
case KINC_G5_MIPMAP_FILTER_POINT:
|
||||
return D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
|
||||
case KINC_G5_MIPMAP_FILTER_LINEAR:
|
||||
return D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_ANISOTROPIC:
|
||||
return D3D12_FILTER_ANISOTROPIC;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_LINEAR:
|
||||
switch (magnification) {
|
||||
case KINC_G5_TEXTURE_FILTER_POINT:
|
||||
switch (mipmap) {
|
||||
case KINC_G5_MIPMAP_FILTER_NONE:
|
||||
case KINC_G5_MIPMAP_FILTER_POINT:
|
||||
return D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT;
|
||||
case KINC_G5_MIPMAP_FILTER_LINEAR:
|
||||
return D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_LINEAR:
|
||||
switch (mipmap) {
|
||||
case KINC_G5_MIPMAP_FILTER_NONE:
|
||||
case KINC_G5_MIPMAP_FILTER_POINT:
|
||||
return D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
case KINC_G5_MIPMAP_FILTER_LINEAR:
|
||||
return D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_ANISOTROPIC:
|
||||
return D3D12_FILTER_ANISOTROPIC;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_ANISOTROPIC:
|
||||
return D3D12_FILTER_ANISOTROPIC;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
}
|
||||
|
||||
static D3D12_FILTER convert_comparison_filter(kinc_g5_texture_filter_t minification, kinc_g5_texture_filter_t magnification, kinc_g5_mipmap_filter_t mipmap) {
|
||||
switch (minification) {
|
||||
case KINC_G5_TEXTURE_FILTER_POINT:
|
||||
switch (magnification) {
|
||||
case KINC_G5_TEXTURE_FILTER_POINT:
|
||||
switch (mipmap) {
|
||||
case KINC_G5_MIPMAP_FILTER_NONE:
|
||||
case KINC_G5_MIPMAP_FILTER_POINT:
|
||||
return D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
|
||||
case KINC_G5_MIPMAP_FILTER_LINEAR:
|
||||
return D3D12_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_LINEAR:
|
||||
switch (mipmap) {
|
||||
case KINC_G5_MIPMAP_FILTER_NONE:
|
||||
case KINC_G5_MIPMAP_FILTER_POINT:
|
||||
return D3D12_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT;
|
||||
case KINC_G5_MIPMAP_FILTER_LINEAR:
|
||||
return D3D12_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_ANISOTROPIC:
|
||||
return D3D12_FILTER_COMPARISON_ANISOTROPIC;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_LINEAR:
|
||||
switch (magnification) {
|
||||
case KINC_G5_TEXTURE_FILTER_POINT:
|
||||
switch (mipmap) {
|
||||
case KINC_G5_MIPMAP_FILTER_NONE:
|
||||
case KINC_G5_MIPMAP_FILTER_POINT:
|
||||
return D3D12_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT;
|
||||
case KINC_G5_MIPMAP_FILTER_LINEAR:
|
||||
return D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_LINEAR:
|
||||
switch (mipmap) {
|
||||
case KINC_G5_MIPMAP_FILTER_NONE:
|
||||
case KINC_G5_MIPMAP_FILTER_POINT:
|
||||
return D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
|
||||
case KINC_G5_MIPMAP_FILTER_LINEAR:
|
||||
return D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_ANISOTROPIC:
|
||||
return D3D12_FILTER_COMPARISON_ANISOTROPIC;
|
||||
}
|
||||
case KINC_G5_TEXTURE_FILTER_ANISOTROPIC:
|
||||
return D3D12_FILTER_COMPARISON_ANISOTROPIC;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
|
||||
}
|
||||
|
||||
void kinc_g5_sampler_init(kinc_g5_sampler_t *sampler, const kinc_g5_sampler_options_t *options) {
|
||||
D3D12_DESCRIPTOR_HEAP_DESC descHeapSampler = {};
|
||||
descHeapSampler.NumDescriptors = 2;
|
||||
descHeapSampler.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
descHeapSampler.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
device->CreateDescriptorHeap(&descHeapSampler, IID_GRAPHICS_PPV_ARGS(&sampler->impl.sampler_heap));
|
||||
|
||||
D3D12_SAMPLER_DESC samplerDesc;
|
||||
ZeroMemory(&samplerDesc, sizeof(D3D12_SAMPLER_DESC));
|
||||
samplerDesc.Filter = options->is_comparison ? convert_comparison_filter(options->minification_filter, options->magnification_filter, options->mipmap_filter)
|
||||
: convert_filter(options->minification_filter, options->magnification_filter, options->mipmap_filter);
|
||||
samplerDesc.AddressU = convert_texture_addressing(options->u_addressing);
|
||||
samplerDesc.AddressV = convert_texture_addressing(options->v_addressing);
|
||||
samplerDesc.AddressW = convert_texture_addressing(options->w_addressing);
|
||||
samplerDesc.MinLOD = options->lod_min_clamp;
|
||||
samplerDesc.MaxLOD = options->lod_max_clamp;
|
||||
samplerDesc.MipLODBias = 0.0f;
|
||||
samplerDesc.MaxAnisotropy = options->max_anisotropy;
|
||||
samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
||||
device->CreateSampler(&samplerDesc, sampler->impl.sampler_heap->GetCPUDescriptorHandleForHeapStart());
|
||||
}
|
||||
|
||||
void kinc_g5_sampler_destroy(kinc_g5_sampler_t *sampler) {}
|
||||
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
struct ID3D12DescriptorHeap;
|
||||
|
||||
typedef struct kinc_g5_sampler_impl {
|
||||
struct ID3D12DescriptorHeap *sampler_heap;
|
||||
} kinc_g5_sampler_impl_t;
|
||||
@ -0,0 +1,87 @@
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
#include <kinc/graphics5/shader.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
void kinc_g5_shader_init(kinc_g5_shader_t *shader, const void *_data, size_t length, kinc_g5_shader_type_t type) {
|
||||
memset(shader->impl.constants, 0, sizeof(shader->impl.constants));
|
||||
memset(shader->impl.attributes, 0, sizeof(shader->impl.attributes));
|
||||
memset(shader->impl.textures, 0, sizeof(shader->impl.textures));
|
||||
|
||||
unsigned index = 0;
|
||||
uint8_t *data = (uint8_t *)_data;
|
||||
|
||||
int attributesCount = data[index++];
|
||||
for (int i = 0; i < attributesCount; ++i) {
|
||||
char name[64];
|
||||
for (unsigned i2 = 0; i2 < 63; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
strcpy(shader->impl.attributes[i].name, name);
|
||||
shader->impl.attributes[i].attribute = data[index++];
|
||||
}
|
||||
|
||||
uint8_t texCount = data[index++];
|
||||
for (unsigned i = 0; i < texCount; ++i) {
|
||||
char name[64];
|
||||
for (unsigned i2 = 0; i2 < 63; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
strcpy(shader->impl.textures[i].name, name);
|
||||
shader->impl.textures[i].texture = data[index++];
|
||||
}
|
||||
shader->impl.texturesCount = texCount;
|
||||
|
||||
uint8_t constantCount = data[index++];
|
||||
shader->impl.constantsSize = 0;
|
||||
for (unsigned i = 0; i < constantCount; ++i) {
|
||||
char name[64];
|
||||
for (unsigned i2 = 0; i2 < 63; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
ShaderConstant constant;
|
||||
memcpy(&constant.offset, &data[index], sizeof(constant.offset));
|
||||
index += 4;
|
||||
memcpy(&constant.size, &data[index], sizeof(constant.size));
|
||||
index += 4;
|
||||
#ifdef KINC_WINDOWS
|
||||
index += 2; // columns and rows
|
||||
#endif
|
||||
strcpy(constant.name, name);
|
||||
shader->impl.constants[i] = constant;
|
||||
shader->impl.constantsSize = constant.offset + constant.size;
|
||||
}
|
||||
|
||||
shader->impl.length = (int)length - index;
|
||||
shader->impl.data = (uint8_t *)malloc(shader->impl.length);
|
||||
memcpy(shader->impl.data, &data[index], shader->impl.length);
|
||||
|
||||
switch (type) {
|
||||
case KINC_G5_SHADER_TYPE_VERTEX:
|
||||
// Microsoft::affirm(device->CreateVertexShader(this->data, this->length, nullptr, (ID3D11VertexShader**)&shader));
|
||||
break;
|
||||
case KINC_G5_SHADER_TYPE_FRAGMENT:
|
||||
// Microsoft::affirm(device->CreatePixelShader(this->data, this->length, nullptr, (ID3D11PixelShader**)&shader));
|
||||
break;
|
||||
case KINC_G5_SHADER_TYPE_GEOMETRY:
|
||||
// Microsoft::affirm(device->CreateGeometryShader(this->data, this->length, nullptr, (ID3D11GeometryShader**)&shader));
|
||||
break;
|
||||
case KINC_G5_SHADER_TYPE_TESSELLATION_CONTROL:
|
||||
// Microsoft::affirm(device->CreateHullShader(this->data, this->length, nullptr, (ID3D11HullShader**)&shader));
|
||||
break;
|
||||
case KINC_G5_SHADER_TYPE_TESSELLATION_EVALUATION:
|
||||
// Microsoft::affirm(device->CreateDomainShader(this->data, this->length, nullptr, (ID3D11DomainShader**)&shader));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g5_shader_destroy(kinc_g5_shader_t *shader) {
|
||||
free(shader->impl.data);
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char name[64];
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
} ShaderConstant;
|
||||
|
||||
typedef struct {
|
||||
char name[64];
|
||||
int attribute;
|
||||
} ShaderAttribute;
|
||||
|
||||
typedef struct {
|
||||
char name[64];
|
||||
int texture;
|
||||
} ShaderTexture;
|
||||
|
||||
typedef struct {
|
||||
ShaderConstant constants[32];
|
||||
int constantsSize;
|
||||
ShaderAttribute attributes[32];
|
||||
ShaderTexture textures[32];
|
||||
int texturesCount;
|
||||
|
||||
void *shader;
|
||||
uint8_t *data;
|
||||
int length;
|
||||
} Shader5Impl;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,455 @@
|
||||
#include "texture.h"
|
||||
|
||||
#include <kinc/graphics5/rendertarget.h>
|
||||
#include <kinc/graphics5/texture.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
static const int heapSize = 1024;
|
||||
|
||||
#if defined(KINC_WINDOWS) || defined(KINC_WINDOWSAPP)
|
||||
/*static int d3d12_textureAlignment() {
|
||||
return D3D12_TEXTURE_DATA_PITCH_ALIGNMENT;
|
||||
}*/
|
||||
#else
|
||||
int d3d12_textureAlignment();
|
||||
#endif
|
||||
|
||||
void kinc_g5_internal_reset_textures(struct kinc_g5_command_list *list) {
|
||||
for (int i = 0; i < KINC_INTERNAL_G5_TEXTURE_COUNT; ++i) {
|
||||
list->impl.currentRenderTargets[i] = NULL;
|
||||
list->impl.currentTextures[i] = NULL;
|
||||
list->impl.current_samplers[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline UINT64 GetRequiredIntermediateSize(ID3D12Resource *destinationResource, UINT FirstSubresource, UINT NumSubresources) {
|
||||
D3D12_RESOURCE_DESC desc = destinationResource->GetDesc();
|
||||
UINT64 requiredSize = 0;
|
||||
device->GetCopyableFootprints(&desc, FirstSubresource, NumSubresources, 0, NULL, NULL, NULL, &requiredSize);
|
||||
return requiredSize;
|
||||
}
|
||||
|
||||
static DXGI_FORMAT convertImageFormat(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_RGB24:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case KINC_IMAGE_FORMAT_BGRA32:
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
default:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
static int formatByteSize(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
return 16;
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
return 8;
|
||||
case KINC_IMAGE_FORMAT_RGB24:
|
||||
return 4;
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
return 4;
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
return 2;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return 1;
|
||||
case KINC_IMAGE_FORMAT_BGRA32:
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
return 4;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g5_internal_set_textures(kinc_g5_command_list_t *list) {
|
||||
int texture_count = 0;
|
||||
for (int i = 0; i < KINC_INTERNAL_G5_TEXTURE_COUNT; ++i) {
|
||||
if ((list->impl.currentRenderTargets[i] != NULL || list->impl.currentTextures[i] != NULL) && list->impl.current_samplers[i] != NULL) {
|
||||
texture_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (texture_count > 0) {
|
||||
int srvStep = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
int samplerStep = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
|
||||
if (list->impl.heapIndex + KINC_INTERNAL_G5_TEXTURE_COUNT >= heapSize) {
|
||||
list->impl.heapIndex = 0;
|
||||
}
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE srvGpu = list->impl.srvHeap->GetGPUDescriptorHandleForHeapStart();
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE samplerGpu = list->impl.samplerHeap->GetGPUDescriptorHandleForHeapStart();
|
||||
srvGpu.ptr += list->impl.heapIndex * srvStep;
|
||||
samplerGpu.ptr += list->impl.heapIndex * samplerStep;
|
||||
|
||||
for (int i = 0; i < KINC_INTERNAL_G5_TEXTURE_COUNT; ++i) {
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE srvCpu = list->impl.srvHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE samplerCpu = list->impl.samplerHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
srvCpu.ptr += list->impl.heapIndex * srvStep;
|
||||
samplerCpu.ptr += list->impl.heapIndex * samplerStep;
|
||||
++list->impl.heapIndex;
|
||||
|
||||
if ((list->impl.currentRenderTargets[i] != NULL || list->impl.currentTextures[i] != NULL) && list->impl.current_samplers[i] != NULL) {
|
||||
ID3D12DescriptorHeap *samplerDescriptorHeap = list->impl.current_samplers[i]->impl.sampler_heap;
|
||||
|
||||
if (list->impl.currentRenderTargets[i] != NULL) {
|
||||
bool is_depth = list->impl.currentRenderTargets[i]->impl.stage_depth == i;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE sourceCpu =
|
||||
is_depth ? list->impl.currentRenderTargets[i]->impl.srvDepthDescriptorHeap->GetCPUDescriptorHandleForHeapStart()
|
||||
: list->impl.currentRenderTargets[i]->impl.srvDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
device->CopyDescriptorsSimple(1, srvCpu, sourceCpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
device->CopyDescriptorsSimple(1, samplerCpu, samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart(),
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
}
|
||||
else {
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE sourceCpu = list->impl.currentTextures[i]->impl.srvDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
device->CopyDescriptorsSimple(1, srvCpu, sourceCpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
device->CopyDescriptorsSimple(1, samplerCpu, samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart(),
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
||||
}
|
||||
}
|
||||
else {
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
|
||||
ZeroMemory(&shaderResourceViewDesc, sizeof(shaderResourceViewDesc));
|
||||
shaderResourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderResourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
shaderResourceViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
shaderResourceViewDesc.Texture2D.MipLevels = 1;
|
||||
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||
device->CreateShaderResourceView(NULL, &shaderResourceViewDesc, srvCpu);
|
||||
|
||||
D3D12_SAMPLER_DESC samplerDesc;
|
||||
ZeroMemory(&samplerDesc, sizeof(D3D12_SAMPLER_DESC));
|
||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
samplerDesc.MinLOD = 0.0f;
|
||||
samplerDesc.MaxLOD = 1.0f;
|
||||
samplerDesc.MipLODBias = 0.0f;
|
||||
samplerDesc.MaxAnisotropy = 1;
|
||||
samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
||||
device->CreateSampler(&samplerDesc, samplerCpu);
|
||||
}
|
||||
}
|
||||
|
||||
ID3D12DescriptorHeap *heaps[2] = {list->impl.srvHeap, list->impl.samplerHeap};
|
||||
list->impl._commandList->SetDescriptorHeaps(2, heaps);
|
||||
if (compute_pipeline_set) {
|
||||
list->impl._commandList->SetComputeRootDescriptorTable(0, srvGpu);
|
||||
list->impl._commandList->SetComputeRootDescriptorTable(1, srvGpu);
|
||||
list->impl._commandList->SetComputeRootDescriptorTable(2, samplerGpu);
|
||||
}
|
||||
else {
|
||||
list->impl._commandList->SetGraphicsRootDescriptorTable(0, srvGpu);
|
||||
list->impl._commandList->SetGraphicsRootDescriptorTable(1, samplerGpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void createHeaps(kinc_g5_command_list_t *list) {
|
||||
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
|
||||
heapDesc.NumDescriptors = heapSize;
|
||||
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
device->CreateDescriptorHeap(&heapDesc, IID_GRAPHICS_PPV_ARGS(&list->impl.srvHeap));
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC samplerHeapDesc = {};
|
||||
samplerHeapDesc.NumDescriptors = heapSize;
|
||||
samplerHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
samplerHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
device->CreateDescriptorHeap(&samplerHeapDesc, IID_GRAPHICS_PPV_ARGS(&list->impl.samplerHeap));
|
||||
}
|
||||
|
||||
extern "C" void kinc_memory_emergency();
|
||||
|
||||
void kinc_g5_texture_init_from_image(kinc_g5_texture_t *texture, kinc_image_t *image) {
|
||||
memset(&texture->impl, 0, sizeof(texture->impl));
|
||||
texture->impl.stage = 0;
|
||||
texture->impl.mipmap = true;
|
||||
texture->texWidth = image->width;
|
||||
texture->texHeight = image->height;
|
||||
|
||||
DXGI_FORMAT d3dformat = convertImageFormat(image->format);
|
||||
int formatSize = formatByteSize(image->format);
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapPropertiesDefault;
|
||||
heapPropertiesDefault.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapPropertiesDefault.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapPropertiesDefault.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapPropertiesDefault.CreationNodeMask = 1;
|
||||
heapPropertiesDefault.VisibleNodeMask = 1;
|
||||
|
||||
D3D12_RESOURCE_DESC resourceDescTex;
|
||||
resourceDescTex.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
resourceDescTex.Alignment = 0;
|
||||
resourceDescTex.Width = texture->texWidth;
|
||||
resourceDescTex.Height = texture->texHeight;
|
||||
resourceDescTex.DepthOrArraySize = 1;
|
||||
resourceDescTex.MipLevels = 1;
|
||||
resourceDescTex.Format = d3dformat;
|
||||
resourceDescTex.SampleDesc.Count = 1;
|
||||
resourceDescTex.SampleDesc.Quality = 0;
|
||||
resourceDescTex.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
resourceDescTex.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
HRESULT result = device->CreateCommittedResource(&heapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &resourceDescTex, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
NULL, IID_GRAPHICS_PPV_ARGS(&texture->impl.image));
|
||||
if (result != S_OK) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
kinc_memory_emergency();
|
||||
result = device->CreateCommittedResource(&heapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &resourceDescTex, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
NULL, IID_GRAPHICS_PPV_ARGS(&texture->impl.image));
|
||||
if (result == S_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapPropertiesUpload;
|
||||
heapPropertiesUpload.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
heapPropertiesUpload.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapPropertiesUpload.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapPropertiesUpload.CreationNodeMask = 1;
|
||||
heapPropertiesUpload.VisibleNodeMask = 1;
|
||||
|
||||
const UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture->impl.image, 0, 1);
|
||||
D3D12_RESOURCE_DESC resourceDescBuffer;
|
||||
resourceDescBuffer.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resourceDescBuffer.Alignment = 0;
|
||||
resourceDescBuffer.Width = uploadBufferSize;
|
||||
resourceDescBuffer.Height = 1;
|
||||
resourceDescBuffer.DepthOrArraySize = 1;
|
||||
resourceDescBuffer.MipLevels = 1;
|
||||
resourceDescBuffer.Format = DXGI_FORMAT_UNKNOWN;
|
||||
resourceDescBuffer.SampleDesc.Count = 1;
|
||||
resourceDescBuffer.SampleDesc.Quality = 0;
|
||||
resourceDescBuffer.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resourceDescBuffer.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
result = device->CreateCommittedResource(&heapPropertiesUpload, D3D12_HEAP_FLAG_NONE, &resourceDescBuffer, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&texture->impl.uploadImage));
|
||||
if (result != S_OK) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
kinc_memory_emergency();
|
||||
result = device->CreateCommittedResource(&heapPropertiesUpload, D3D12_HEAP_FLAG_NONE, &resourceDescBuffer, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&texture->impl.uploadImage));
|
||||
if (result == S_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
texture->impl.stride = (int)ceilf(uploadBufferSize / (float)(image->height * d3d12_textureAlignment())) * d3d12_textureAlignment();
|
||||
|
||||
BYTE *pixel;
|
||||
texture->impl.uploadImage->Map(0, NULL, (void **)&pixel);
|
||||
int pitch = kinc_g5_texture_stride(texture);
|
||||
for (int y = 0; y < texture->texHeight; ++y) {
|
||||
memcpy(&pixel[y * pitch], &((uint8_t *)image->data)[y * texture->texWidth * formatSize], texture->texWidth * formatSize);
|
||||
}
|
||||
texture->impl.uploadImage->Unmap(0, NULL);
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {};
|
||||
descriptorHeapDesc.NumDescriptors = 1;
|
||||
|
||||
descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
descriptorHeapDesc.NodeMask = 0;
|
||||
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
|
||||
device->CreateDescriptorHeap(&descriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(&texture->impl.srvDescriptorHeap));
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
|
||||
ZeroMemory(&shaderResourceViewDesc, sizeof(shaderResourceViewDesc));
|
||||
shaderResourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderResourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
shaderResourceViewDesc.Format = d3dformat;
|
||||
shaderResourceViewDesc.Texture2D.MipLevels = 1;
|
||||
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||
|
||||
device->CreateShaderResourceView(texture->impl.image, &shaderResourceViewDesc, texture->impl.srvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
}
|
||||
|
||||
void create_texture(struct kinc_g5_texture *texture, int width, int height, kinc_image_format_t format, D3D12_RESOURCE_FLAGS flags) {
|
||||
// kinc_image_init(&texture->image, width, height, format, readable);
|
||||
memset(&texture->impl, 0, sizeof(texture->impl));
|
||||
texture->impl.stage = 0;
|
||||
texture->impl.mipmap = true;
|
||||
texture->texWidth = width;
|
||||
texture->texHeight = height;
|
||||
|
||||
DXGI_FORMAT d3dformat = convertImageFormat(format);
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapPropertiesDefault;
|
||||
heapPropertiesDefault.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
heapPropertiesDefault.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapPropertiesDefault.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapPropertiesDefault.CreationNodeMask = 1;
|
||||
heapPropertiesDefault.VisibleNodeMask = 1;
|
||||
|
||||
D3D12_RESOURCE_DESC resourceDescTex;
|
||||
resourceDescTex.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
resourceDescTex.Alignment = 0;
|
||||
resourceDescTex.Width = texture->texWidth;
|
||||
resourceDescTex.Height = texture->texHeight;
|
||||
resourceDescTex.DepthOrArraySize = 1;
|
||||
resourceDescTex.MipLevels = 1;
|
||||
resourceDescTex.Format = d3dformat;
|
||||
resourceDescTex.SampleDesc.Count = 1;
|
||||
resourceDescTex.SampleDesc.Quality = 0;
|
||||
resourceDescTex.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
resourceDescTex.Flags = flags;
|
||||
|
||||
HRESULT result = device->CreateCommittedResource(&heapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &resourceDescTex, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
NULL, IID_GRAPHICS_PPV_ARGS(&texture->impl.image));
|
||||
if (result != S_OK) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
kinc_memory_emergency();
|
||||
result = device->CreateCommittedResource(&heapPropertiesDefault, D3D12_HEAP_FLAG_NONE, &resourceDescTex, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
NULL, IID_GRAPHICS_PPV_ARGS(&texture->impl.image));
|
||||
if (result == S_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapPropertiesUpload;
|
||||
heapPropertiesUpload.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
heapPropertiesUpload.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapPropertiesUpload.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapPropertiesUpload.CreationNodeMask = 1;
|
||||
heapPropertiesUpload.VisibleNodeMask = 1;
|
||||
|
||||
const UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture->impl.image, 0, 1);
|
||||
D3D12_RESOURCE_DESC resourceDescBuffer;
|
||||
resourceDescBuffer.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resourceDescBuffer.Alignment = 0;
|
||||
resourceDescBuffer.Width = uploadBufferSize;
|
||||
resourceDescBuffer.Height = 1;
|
||||
resourceDescBuffer.DepthOrArraySize = 1;
|
||||
resourceDescBuffer.MipLevels = 1;
|
||||
resourceDescBuffer.Format = DXGI_FORMAT_UNKNOWN;
|
||||
resourceDescBuffer.SampleDesc.Count = 1;
|
||||
resourceDescBuffer.SampleDesc.Quality = 0;
|
||||
resourceDescBuffer.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resourceDescBuffer.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
result = device->CreateCommittedResource(&heapPropertiesUpload, D3D12_HEAP_FLAG_NONE, &resourceDescBuffer, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&texture->impl.uploadImage));
|
||||
if (result != S_OK) {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
kinc_memory_emergency();
|
||||
result = device->CreateCommittedResource(&heapPropertiesUpload, D3D12_HEAP_FLAG_NONE, &resourceDescBuffer, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&texture->impl.uploadImage));
|
||||
if (result == S_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
texture->impl.stride = (int)ceilf(uploadBufferSize / (float)(height * d3d12_textureAlignment())) * d3d12_textureAlignment();
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc;
|
||||
ZeroMemory(&descriptorHeapDesc, sizeof(descriptorHeapDesc));
|
||||
descriptorHeapDesc.NumDescriptors = 1;
|
||||
|
||||
descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
descriptorHeapDesc.NodeMask = 0;
|
||||
descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
|
||||
device->CreateDescriptorHeap(&descriptorHeapDesc, IID_GRAPHICS_PPV_ARGS(&texture->impl.srvDescriptorHeap));
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc = {};
|
||||
shaderResourceViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderResourceViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
shaderResourceViewDesc.Format = d3dformat;
|
||||
shaderResourceViewDesc.Texture2D.MipLevels = 1;
|
||||
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||
|
||||
device->CreateShaderResourceView(texture->impl.image, &shaderResourceViewDesc, texture->impl.srvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
}
|
||||
|
||||
void kinc_g5_texture_init(struct kinc_g5_texture *texture, int width, int height, kinc_image_format_t format) {
|
||||
create_texture(texture, width, height, format, D3D12_RESOURCE_FLAG_NONE);
|
||||
}
|
||||
|
||||
void kinc_g5_texture_init3d(kinc_g5_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {
|
||||
// kinc_image_init3d(&texture->image, width, height, depth, format, readable);
|
||||
}
|
||||
|
||||
void kinc_g5_texture_init_non_sampled_access(struct kinc_g5_texture *texture, int width, int height, kinc_image_format_t format) {
|
||||
create_texture(texture, width, height, format, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
|
||||
}
|
||||
|
||||
void kinc_g5_texture_destroy(struct kinc_g5_texture *texture) {
|
||||
texture->impl.image->Release();
|
||||
texture->impl.uploadImage->Release();
|
||||
texture->impl.srvDescriptorHeap->Release();
|
||||
}
|
||||
|
||||
void kinc_g5_internal_texture_unmipmap(struct kinc_g5_texture *texture) {
|
||||
texture->impl.mipmap = false;
|
||||
}
|
||||
|
||||
void kinc_g5_internal_texture_set(kinc_g5_command_list_t *list, struct kinc_g5_texture *texture, int unit) {
|
||||
if (unit < 0)
|
||||
return;
|
||||
// context->PSSetShaderResources(unit.unit, 1, &view);
|
||||
texture->impl.stage = unit;
|
||||
list->impl.currentTextures[texture->impl.stage] = texture;
|
||||
list->impl.currentRenderTargets[texture->impl.stage] = NULL;
|
||||
}
|
||||
|
||||
void kinc_g5_internal_sampler_set(kinc_g5_command_list_t *list, kinc_g5_sampler_t *sampler, int unit) {
|
||||
if (unit < 0)
|
||||
return;
|
||||
|
||||
list->impl.current_samplers[unit] = sampler;
|
||||
}
|
||||
|
||||
uint8_t *kinc_g5_texture_lock(struct kinc_g5_texture *texture) {
|
||||
BYTE *pixel;
|
||||
texture->impl.uploadImage->Map(0, NULL, (void **)&pixel);
|
||||
return pixel;
|
||||
}
|
||||
|
||||
void kinc_g5_texture_unlock(struct kinc_g5_texture *texture) {
|
||||
texture->impl.uploadImage->Unmap(0, NULL);
|
||||
}
|
||||
|
||||
void kinc_g5_texture_clear(kinc_g5_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {}
|
||||
|
||||
int kinc_g5_texture_stride(struct kinc_g5_texture *texture) {
|
||||
/*int baseStride = texture->format == KINC_IMAGE_FORMAT_RGBA32 ? (texture->texWidth * 4) : texture->texWidth;
|
||||
if (texture->format == KINC_IMAGE_FORMAT_GREY8) return texture->texWidth; // please investigate further
|
||||
for (int i = 0;; ++i) {
|
||||
if (d3d12_textureAlignment() * i >= baseStride) {
|
||||
return d3d12_textureAlignment() * i;
|
||||
}
|
||||
}*/
|
||||
return texture->impl.stride;
|
||||
}
|
||||
|
||||
void kinc_g5_texture_generate_mipmaps(struct kinc_g5_texture *texture, int levels) {}
|
||||
|
||||
void kinc_g5_texture_set_mipmap(struct kinc_g5_texture *texture, kinc_image_t *mipmap, int level) {}
|
||||
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D12Resource;
|
||||
struct ID3D12DescriptorHeap;
|
||||
struct ID3D12GraphicsCommandList;
|
||||
|
||||
typedef struct {
|
||||
int unit;
|
||||
} TextureUnit5Impl;
|
||||
|
||||
typedef struct {
|
||||
bool mipmap;
|
||||
int stage;
|
||||
int stride;
|
||||
struct ID3D12Resource *image;
|
||||
struct ID3D12Resource *uploadImage;
|
||||
struct ID3D12DescriptorHeap *srvDescriptorHeap;
|
||||
} Texture5Impl;
|
||||
|
||||
struct kinc_g5_texture;
|
||||
struct kinc_g5_command_list;
|
||||
|
||||
void kinc_g5_internal_set_textures(struct kinc_g5_command_list *commandList);
|
||||
void kinc_g5_internal_texture_set(struct kinc_g5_command_list *commandList, struct kinc_g5_texture *texture, int unit);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,123 @@
|
||||
#include "vertexbuffer.h"
|
||||
|
||||
#include <kinc/graphics5/vertexbuffer.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
|
||||
kinc_g5_vertex_buffer_t *_current_vertex_buffer = NULL;
|
||||
|
||||
void kinc_g5_vertex_buffer_init(kinc_g5_vertex_buffer_t *buffer, int count, kinc_g5_vertex_structure_t *structure, bool gpuMemory, int instanceDataStepRate) {
|
||||
buffer->impl.myCount = count;
|
||||
|
||||
// static_assert(sizeof(D3D12VertexBufferView) == sizeof(D3D12_VERTEX_BUFFER_VIEW), "Something is wrong with D3D12IVertexBufferView");
|
||||
|
||||
buffer->impl.myStride = 0;
|
||||
for (int i = 0; i < structure->size; ++i) {
|
||||
buffer->impl.myStride += kinc_g4_vertex_data_size(structure->elements[i].data);
|
||||
}
|
||||
|
||||
int uploadBufferSize = buffer->impl.myStride * buffer->impl.myCount;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heapProperties;
|
||||
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
heapProperties.CreationNodeMask = 1;
|
||||
heapProperties.VisibleNodeMask = 1;
|
||||
|
||||
D3D12_RESOURCE_DESC resourceDesc;
|
||||
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
resourceDesc.Alignment = 0;
|
||||
resourceDesc.Width = uploadBufferSize;
|
||||
resourceDesc.Height = 1;
|
||||
resourceDesc.DepthOrArraySize = 1;
|
||||
resourceDesc.MipLevels = 1;
|
||||
resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
resourceDesc.SampleDesc.Count = 1;
|
||||
resourceDesc.SampleDesc.Quality = 0;
|
||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
IID_GRAPHICS_PPV_ARGS(&buffer->impl.uploadBuffer));
|
||||
|
||||
// device_->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES (D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE,
|
||||
// &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
|
||||
// D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&vertexBuffer));
|
||||
|
||||
buffer->impl.view.BufferLocation = buffer->impl.uploadBuffer->GetGPUVirtualAddress();
|
||||
buffer->impl.view.SizeInBytes = uploadBufferSize;
|
||||
buffer->impl.view.StrideInBytes = buffer->impl.myStride;
|
||||
|
||||
buffer->impl.lastStart = 0;
|
||||
buffer->impl.lastCount = kinc_g5_vertex_buffer_count(buffer);
|
||||
}
|
||||
|
||||
void kinc_g5_vertex_buffer_destroy(kinc_g5_vertex_buffer_t *buffer) {
|
||||
// buffer->impl.vertexBuffer->Release();
|
||||
buffer->impl.uploadBuffer->Release();
|
||||
}
|
||||
|
||||
float *kinc_g5_vertex_buffer_lock_all(kinc_g5_vertex_buffer_t *buffer) {
|
||||
return kinc_g5_vertex_buffer_lock(buffer, 0, kinc_g5_vertex_buffer_count(buffer));
|
||||
}
|
||||
|
||||
float *kinc_g5_vertex_buffer_lock(kinc_g5_vertex_buffer_t *buffer, int start, int count) {
|
||||
buffer->impl.lastStart = start;
|
||||
buffer->impl.lastCount = count;
|
||||
|
||||
D3D12_RANGE range;
|
||||
range.Begin = start * buffer->impl.myStride;
|
||||
range.End = (start + count) * buffer->impl.myStride;
|
||||
|
||||
void *p;
|
||||
buffer->impl.uploadBuffer->Map(0, &range, &p);
|
||||
byte *bytes = (byte *)p;
|
||||
bytes += start * buffer->impl.myStride;
|
||||
return (float *)bytes;
|
||||
}
|
||||
|
||||
void kinc_g5_vertex_buffer_unlock_all(kinc_g5_vertex_buffer_t *buffer) {
|
||||
D3D12_RANGE range;
|
||||
range.Begin = buffer->impl.lastStart * buffer->impl.myStride;
|
||||
range.End = (buffer->impl.lastStart + buffer->impl.lastCount) * buffer->impl.myStride;
|
||||
buffer->impl.uploadBuffer->Unmap(0, &range);
|
||||
|
||||
// view.BufferLocation = uploadBuffer->GetGPUVirtualAddress() + myStart * myStride;
|
||||
|
||||
// commandList->CopyBufferRegion(vertexBuffer, 0, uploadBuffer, 0, count() * stride());
|
||||
// CD3DX12_RESOURCE_BARRIER barriers[1] = { CD3DX12_RESOURCE_BARRIER::Transition(vertexBuffer, D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
// D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) };
|
||||
// commandList->ResourceBarrier(1, barriers);
|
||||
}
|
||||
|
||||
void kinc_g5_vertex_buffer_unlock(kinc_g5_vertex_buffer_t *buffer, int count) {
|
||||
D3D12_RANGE range;
|
||||
range.Begin = buffer->impl.lastStart * buffer->impl.myStride;
|
||||
range.End = (buffer->impl.lastStart + count) * buffer->impl.myStride;
|
||||
buffer->impl.uploadBuffer->Unmap(0, &range);
|
||||
|
||||
// view.BufferLocation = uploadBuffer->GetGPUVirtualAddress() + myStart * myStride;
|
||||
|
||||
// commandList->CopyBufferRegion(vertexBuffer, 0, uploadBuffer, 0, count() * stride());
|
||||
// CD3DX12_RESOURCE_BARRIER barriers[1] = { CD3DX12_RESOURCE_BARRIER::Transition(vertexBuffer, D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
// D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) };
|
||||
// commandList->ResourceBarrier(1, barriers);
|
||||
}
|
||||
|
||||
int kinc_g5_internal_vertex_buffer_set(kinc_g5_vertex_buffer_t *buffer, int offset) {
|
||||
// UINT stride = myStride;
|
||||
// UINT offset = 0;
|
||||
// context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
|
||||
_current_vertex_buffer = buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kinc_g5_vertex_buffer_count(kinc_g5_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.myCount;
|
||||
}
|
||||
|
||||
int kinc_g5_vertex_buffer_stride(kinc_g5_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.myStride;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D12Resource;
|
||||
|
||||
struct D3D12VertexBufferView {
|
||||
__int64 BufferLocation;
|
||||
unsigned int SizeInBytes;
|
||||
unsigned int StrideInBytes;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
// ID3D12Resource* vertexBuffer;
|
||||
struct ID3D12Resource *uploadBuffer;
|
||||
struct D3D12VertexBufferView view;
|
||||
|
||||
int myCount;
|
||||
int myStride;
|
||||
int lastStart;
|
||||
int lastCount;
|
||||
// float* vertices;
|
||||
// static VertexBuffer5Impl* _current;
|
||||
} VertexBuffer5Impl;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,610 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// Don't include this file directly - use pix3.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _PIXEventsCommon_H_
|
||||
#define _PIXEventsCommon_H_
|
||||
|
||||
//
|
||||
// The PIXBeginEvent and PIXSetMarker functions have an optimized path for
|
||||
// copying strings that work by copying 128-bit or 64-bits at a time. In some
|
||||
// circumstances this may result in PIX logging the remaining memory after the
|
||||
// null terminator.
|
||||
//
|
||||
// By default this optimization is enabled unless Address Sanitizer is enabled,
|
||||
// since this optimization can trigger a global-buffer-overflow when copying
|
||||
// string literals.
|
||||
//
|
||||
// The PIX_ENABLE_BLOCK_ARGUMENT_COPY controls whether or not this optimization
|
||||
// is enabled. Applications may also explicitly set this macro to 0 to disable
|
||||
// the optimization if necessary.
|
||||
//
|
||||
|
||||
// Check for Address Sanitizer on either Clang or MSVC
|
||||
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(address_sanitizer)
|
||||
#define PIX_ASAN_ENABLED
|
||||
#endif
|
||||
#elif defined(__SANITIZE_ADDRESS__)
|
||||
#define PIX_ASAN_ENABLED
|
||||
#endif
|
||||
|
||||
#if defined(PIX_ENABLE_BLOCK_ARGUMENT_COPY)
|
||||
// Previously set values override everything
|
||||
# define PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET 0
|
||||
#elif defined(PIX_ASAN_ENABLED)
|
||||
// Disable block argument copy when address sanitizer is enabled
|
||||
#define PIX_ENABLE_BLOCK_ARGUMENT_COPY 0
|
||||
#define PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET 1
|
||||
#endif
|
||||
|
||||
#if !defined(PIX_ENABLE_BLOCK_ARGUMENT_COPY)
|
||||
// Default to enabled.
|
||||
#define PIX_ENABLE_BLOCK_ARGUMENT_COPY 1
|
||||
#define PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET 1
|
||||
#endif
|
||||
|
||||
struct PIXEventsBlockInfo;
|
||||
|
||||
struct PIXEventsThreadInfo
|
||||
{
|
||||
PIXEventsBlockInfo* block;
|
||||
UINT64* biasedLimit;
|
||||
UINT64* destination;
|
||||
};
|
||||
|
||||
extern "C" UINT64 WINAPI PIXEventsReplaceBlock(PIXEventsThreadInfo * threadInfo, bool getEarliestTime) noexcept;
|
||||
|
||||
#define PIX_EVENT_METADATA_NONE 0x0
|
||||
#define PIX_EVENT_METADATA_ON_CONTEXT 0x1
|
||||
#define PIX_EVENT_METADATA_STRING_IS_ANSI 0x2
|
||||
#define PIX_EVENT_METADATA_HAS_COLOR 0xF0
|
||||
|
||||
#ifndef PIX_GAMING_XBOX
|
||||
#include "PIXEventsLegacy.h"
|
||||
#endif
|
||||
|
||||
enum PIXEventType : UINT8
|
||||
{
|
||||
PIXEvent_EndEvent = 0x00,
|
||||
PIXEvent_BeginEvent = 0x01,
|
||||
PIXEvent_SetMarker = 0x02,
|
||||
};
|
||||
|
||||
static const UINT64 PIXEventsReservedRecordSpaceQwords = 64;
|
||||
//this is used to make sure SSE string copy always will end 16-byte write in the current block
|
||||
//this way only a check if destination < limit can be performed, instead of destination < limit - 1
|
||||
//since both these are UINT64* and SSE writes in 16 byte chunks, 8 bytes are kept in reserve
|
||||
//so even if SSE overwrites 8-15 extra bytes, those will still belong to the correct block
|
||||
//on next iteration check destination will be greater than limit
|
||||
//this is used as well for fixed size UMD events and PIXEndEvent since these require less space
|
||||
//than other variable length user events and do not need big reserved space
|
||||
static const UINT64 PIXEventsReservedTailSpaceQwords = 2;
|
||||
static const UINT64 PIXEventsSafeFastCopySpaceQwords = PIXEventsReservedRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
|
||||
static const UINT64 PIXEventsGraphicsRecordSpaceQwords = 64;
|
||||
|
||||
//Bits 7-19 (13 bits)
|
||||
static const UINT64 PIXEventsBlockEndMarker = 0x00000000000FFF80;
|
||||
|
||||
|
||||
// V2 events
|
||||
|
||||
// Bits 00..06 (7 bits) - Size in QWORDS
|
||||
static const UINT64 PIXEventsSizeWriteMask = 0x000000000000007F;
|
||||
static const UINT64 PIXEventsSizeBitShift = 0;
|
||||
static const UINT64 PIXEventsSizeReadMask = PIXEventsSizeWriteMask << PIXEventsSizeBitShift;
|
||||
static const UINT64 PIXEventsSizeMax = (1ull << 7) - 1ull;
|
||||
|
||||
// Bits 07..11 (5 bits) - Event Type
|
||||
static const UINT64 PIXEventsTypeWriteMask = 0x000000000000001F;
|
||||
static const UINT64 PIXEventsTypeBitShift = 7;
|
||||
static const UINT64 PIXEventsTypeReadMask = PIXEventsTypeWriteMask << PIXEventsTypeBitShift;
|
||||
|
||||
// Bits 12..19 (8 bits) - Event Specific Metadata
|
||||
static const UINT64 PIXEventsMetadataWriteMask = 0x00000000000000FF;
|
||||
static const UINT64 PIXEventsMetadataBitShift = 12;
|
||||
static const UINT64 PIXEventsMetadataReadMask = PIXEventsMetadataWriteMask << PIXEventsMetadataBitShift;
|
||||
|
||||
// Buts 20..63 (44 bits) - Timestamp
|
||||
static const UINT64 PIXEventsTimestampWriteMask = 0x00000FFFFFFFFFFF;
|
||||
static const UINT64 PIXEventsTimestampBitShift = 20;
|
||||
static const UINT64 PIXEventsTimestampReadMask = PIXEventsTimestampWriteMask << PIXEventsTimestampBitShift;
|
||||
|
||||
inline UINT64 PIXEncodeEventInfo(UINT64 timestamp, PIXEventType eventType, UINT8 eventSize, UINT8 eventMetadata)
|
||||
{
|
||||
return
|
||||
((timestamp & PIXEventsTimestampWriteMask) << PIXEventsTimestampBitShift) |
|
||||
(((UINT64)eventType & PIXEventsTypeWriteMask) << PIXEventsTypeBitShift) |
|
||||
(((UINT64)eventMetadata & PIXEventsMetadataWriteMask) << PIXEventsMetadataBitShift) |
|
||||
(((UINT64)eventSize & PIXEventsSizeWriteMask) << PIXEventsSizeBitShift);
|
||||
}
|
||||
|
||||
inline UINT8 PIXEncodeIndexColor(UINT8 color)
|
||||
{
|
||||
// There are 8 index colors, indexed 0 (default) to 7
|
||||
return (color & 0x7) << 4;
|
||||
}
|
||||
|
||||
//Bits 60-63 (4)
|
||||
static const UINT64 PIXEventsStringAlignmentWriteMask = 0x000000000000000F;
|
||||
static const UINT64 PIXEventsStringAlignmentReadMask = 0xF000000000000000;
|
||||
static const UINT64 PIXEventsStringAlignmentBitShift = 60;
|
||||
|
||||
//Bits 55-59 (5)
|
||||
static const UINT64 PIXEventsStringCopyChunkSizeWriteMask = 0x000000000000001F;
|
||||
static const UINT64 PIXEventsStringCopyChunkSizeReadMask = 0x0F80000000000000;
|
||||
static const UINT64 PIXEventsStringCopyChunkSizeBitShift = 55;
|
||||
|
||||
//Bit 54
|
||||
static const UINT64 PIXEventsStringIsANSIWriteMask = 0x0000000000000001;
|
||||
static const UINT64 PIXEventsStringIsANSIReadMask = 0x0040000000000000;
|
||||
static const UINT64 PIXEventsStringIsANSIBitShift = 54;
|
||||
|
||||
//Bit 53
|
||||
static const UINT64 PIXEventsStringIsShortcutWriteMask = 0x0000000000000001;
|
||||
static const UINT64 PIXEventsStringIsShortcutReadMask = 0x0020000000000000;
|
||||
static const UINT64 PIXEventsStringIsShortcutBitShift = 53;
|
||||
|
||||
inline void PIXEncodeStringInfo(UINT64*& destination, BOOL isANSI)
|
||||
{
|
||||
const UINT64 encodedStringInfo =
|
||||
((sizeof(UINT64) & PIXEventsStringCopyChunkSizeWriteMask) << PIXEventsStringCopyChunkSizeBitShift) |
|
||||
(((UINT64)isANSI & PIXEventsStringIsANSIWriteMask) << PIXEventsStringIsANSIBitShift);
|
||||
|
||||
*destination++ = encodedStringInfo;
|
||||
}
|
||||
|
||||
template<UINT alignment, class T>
|
||||
inline bool PIXIsPointerAligned(T* pointer)
|
||||
{
|
||||
return !(((UINT64)pointer) & (alignment - 1));
|
||||
}
|
||||
|
||||
// Generic template version slower because of the additional clear write
|
||||
template<class T>
|
||||
inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, T argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*destination = 0ull;
|
||||
*((T*)destination) = argument;
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
// int32 specialization to avoid slower double memory writes
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<INT32>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT32 argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*reinterpret_cast<INT64*>(destination) = static_cast<INT64>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
// unsigned int32 specialization to avoid slower double memory writes
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<UINT32>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT32 argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*destination = static_cast<UINT64>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
// int64 specialization to avoid slower double memory writes
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<INT64>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT64 argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*reinterpret_cast<INT64*>(destination) = argument;
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
// unsigned int64 specialization to avoid slower double memory writes
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<UINT64>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT64 argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*destination = argument;
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
//floats must be cast to double during writing the data to be properly printed later when reading the data
|
||||
//this is needed because when float is passed to varargs function it's cast to double
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<float>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, float argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*reinterpret_cast<double*>(destination) = static_cast<double>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
//char has to be cast to a longer signed integer type
|
||||
//this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<char>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, char argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*reinterpret_cast<INT64*>(destination) = static_cast<INT64>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
//UINT8 has to be cast to a longer unsigned integer type
|
||||
//this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<UINT8>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT8 argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*destination = static_cast<UINT64>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
//bool has to be cast to an integer since it's not explicitly supported by string format routines
|
||||
//there's no format specifier for bool type, but it should work with integer format specifiers
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<bool>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, bool argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*destination = static_cast<UINT64>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
inline void PIXCopyEventStringArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
|
||||
{
|
||||
while (destination < limit)
|
||||
{
|
||||
UINT64 c = static_cast<UINT8>(argument[0]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = 0;
|
||||
return;
|
||||
}
|
||||
UINT64 x = c;
|
||||
c = static_cast<UINT8>(argument[1]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 8;
|
||||
c = static_cast<UINT8>(argument[2]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 16;
|
||||
c = static_cast<UINT8>(argument[3]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 24;
|
||||
c = static_cast<UINT8>(argument[4]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 32;
|
||||
c = static_cast<UINT8>(argument[5]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 40;
|
||||
c = static_cast<UINT8>(argument[6]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 48;
|
||||
c = static_cast<UINT8>(argument[7]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 56;
|
||||
*destination++ = x;
|
||||
argument += 8;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool>
|
||||
inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
|
||||
{
|
||||
PIXEncodeStringInfo(destination, TRUE);
|
||||
PIXCopyEventStringArgumentSlow(destination, limit, argument);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void PIXCopyEventArgumentSlow<false>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
|
||||
{
|
||||
PIXCopyEventStringArgumentSlow(destination, limit, argument);
|
||||
}
|
||||
|
||||
#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
|
||||
inline void PIXCopyEventStringArgumentFast(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
|
||||
{
|
||||
constexpr UINT64 mask1 = 0x0101010101010101ULL;
|
||||
constexpr UINT64 mask2 = 0x8080808080808080ULL;
|
||||
UINT64* source = (UINT64*)argument;
|
||||
|
||||
while (destination < limit)
|
||||
{
|
||||
UINT64 qword = *source++;
|
||||
*destination++ = qword;
|
||||
|
||||
//check if any of the characters is a terminating zero
|
||||
UINT64 isTerminated = (qword - mask1) & (~qword & mask2);
|
||||
|
||||
if (isTerminated)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<PCSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
if (argument != nullptr)
|
||||
{
|
||||
#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
if (PIXIsPointerAligned<8>(argument))
|
||||
{
|
||||
PIXEncodeStringInfo(destination, TRUE);
|
||||
PIXCopyEventStringArgumentFast(destination, limit, argument);
|
||||
}
|
||||
else
|
||||
#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
{
|
||||
PIXCopyEventArgumentSlow<true>(destination, limit, argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*destination++ = 0ull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void PIXCopyStringArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
|
||||
{
|
||||
if (argument != nullptr)
|
||||
{
|
||||
#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
if (PIXIsPointerAligned<8>(argument))
|
||||
{
|
||||
PIXCopyEventStringArgumentFast(destination, limit, argument);
|
||||
}
|
||||
else
|
||||
#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
{
|
||||
PIXCopyEventArgumentSlow<false>(destination, limit, argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*destination++ = 0ull;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<PSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PSTR argument)
|
||||
{
|
||||
PIXCopyEventArgument(destination, limit, (PCSTR)argument);
|
||||
}
|
||||
|
||||
inline void PIXCopyStringArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PSTR argument)
|
||||
{
|
||||
PIXCopyStringArgument(destination, limit, (PCSTR)argument);
|
||||
}
|
||||
|
||||
inline void PIXCopyEventStringArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
|
||||
{
|
||||
while (destination < limit)
|
||||
{
|
||||
UINT64 c = static_cast<UINT16>(argument[0]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = 0;
|
||||
return;
|
||||
}
|
||||
UINT64 x = c;
|
||||
c = static_cast<UINT16>(argument[1]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 16;
|
||||
c = static_cast<UINT16>(argument[2]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 32;
|
||||
c = static_cast<UINT16>(argument[3]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 48;
|
||||
*destination++ = x;
|
||||
argument += 4;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool>
|
||||
inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
|
||||
{
|
||||
PIXEncodeStringInfo(destination, FALSE);
|
||||
PIXCopyEventStringArgumentSlow(destination, limit, argument);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void PIXCopyEventArgumentSlow<false>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
|
||||
{
|
||||
PIXCopyEventStringArgumentSlow(destination, limit, argument);
|
||||
}
|
||||
|
||||
#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
inline void PIXCopyEventStringArgumentFast(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
|
||||
{
|
||||
UINT64* source = (UINT64*)argument;
|
||||
while (destination < limit)
|
||||
{
|
||||
UINT64 qword = *source++;
|
||||
*destination++ = qword;
|
||||
//check if any of the characters is a terminating zero
|
||||
//TODO: check if reversed condition is faster
|
||||
if (!((qword & 0xFFFF000000000000) &&
|
||||
(qword & 0xFFFF00000000) &&
|
||||
(qword & 0xFFFF0000) &&
|
||||
(qword & 0xFFFF)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<PCWSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
if (argument != nullptr)
|
||||
{
|
||||
#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
if (PIXIsPointerAligned<8>(argument))
|
||||
{
|
||||
PIXEncodeStringInfo(destination, FALSE);
|
||||
PIXCopyEventStringArgumentFast(destination, limit, argument);
|
||||
}
|
||||
else
|
||||
#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
{
|
||||
PIXCopyEventArgumentSlow<true>(destination, limit, argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*destination++ = 0ull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void PIXCopyStringArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
|
||||
{
|
||||
if (argument != nullptr)
|
||||
{
|
||||
#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
if (PIXIsPointerAligned<8>(argument))
|
||||
{
|
||||
PIXCopyEventStringArgumentFast(destination, limit, argument);
|
||||
}
|
||||
else
|
||||
#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
{
|
||||
PIXCopyEventArgumentSlow<false>(destination, limit, argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*destination++ = 0ull;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<PWSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PWSTR argument)
|
||||
{
|
||||
PIXCopyEventArgument(destination, limit, (PCWSTR)argument);
|
||||
};
|
||||
|
||||
inline void PIXCopyStringArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PWSTR argument)
|
||||
{
|
||||
PIXCopyStringArgument(destination, limit, (PCWSTR)argument);
|
||||
};
|
||||
|
||||
#if defined(__d3d12_x_h__) || defined(__d3d12_xs_h__) || defined(__d3d12_h__)
|
||||
|
||||
inline void PIXSetGPUMarkerOnContext(_In_ ID3D12GraphicsCommandList* commandList, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
commandList->SetMarker(D3D12_EVENT_METADATA, data, size);
|
||||
}
|
||||
|
||||
inline void PIXSetGPUMarkerOnContext(_In_ ID3D12CommandQueue* commandQueue, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
commandQueue->SetMarker(D3D12_EVENT_METADATA, data, size);
|
||||
}
|
||||
|
||||
inline void PIXBeginGPUEventOnContext(_In_ ID3D12GraphicsCommandList* commandList, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
commandList->BeginEvent(D3D12_EVENT_METADATA, data, size);
|
||||
}
|
||||
|
||||
inline void PIXBeginGPUEventOnContext(_In_ ID3D12CommandQueue* commandQueue, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
commandQueue->BeginEvent(D3D12_EVENT_METADATA, data, size);
|
||||
}
|
||||
|
||||
inline void PIXEndGPUEventOnContext(_In_ ID3D12GraphicsCommandList* commandList)
|
||||
{
|
||||
commandList->EndEvent();
|
||||
}
|
||||
|
||||
inline void PIXEndGPUEventOnContext(_In_ ID3D12CommandQueue* commandQueue)
|
||||
{
|
||||
commandQueue->EndEvent();
|
||||
}
|
||||
|
||||
#endif //__d3d12_h__
|
||||
|
||||
template<class T> struct PIXInferScopedEventType { typedef T Type; };
|
||||
template<class T> struct PIXInferScopedEventType<const T> { typedef T Type; };
|
||||
template<class T> struct PIXInferScopedEventType<T*> { typedef T Type; };
|
||||
template<class T> struct PIXInferScopedEventType<T* const> { typedef T Type; };
|
||||
template<> struct PIXInferScopedEventType<UINT64> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<const UINT64> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<INT64> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<const INT64> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<UINT> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<const UINT> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<INT> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<const INT> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<UINT8> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<const UINT8> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<INT8> { typedef void Type; };
|
||||
template<> struct PIXInferScopedEventType<const INT8> { typedef void Type; };
|
||||
|
||||
#endif //_PIXEventsCommon_H_
|
||||
@ -0,0 +1,565 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
// Don't include this file directly - use pix3.h
|
||||
// This file encodes PIX events in the legacy PIX event format.
|
||||
|
||||
#ifndef _PIXEventsLegacy_H_
|
||||
#define _PIXEventsLegacy_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#if defined(_M_X64) || defined(_M_IX86)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
namespace PixEventsLegacy
|
||||
{
|
||||
enum PIXEventType
|
||||
{
|
||||
PIXEvent_EndEvent = 0x000,
|
||||
PIXEvent_BeginEvent_VarArgs = 0x001,
|
||||
PIXEvent_BeginEvent_NoArgs = 0x002,
|
||||
PIXEvent_SetMarker_VarArgs = 0x007,
|
||||
PIXEvent_SetMarker_NoArgs = 0x008,
|
||||
|
||||
PIXEvent_EndEvent_OnContext = 0x010,
|
||||
PIXEvent_BeginEvent_OnContext_VarArgs = 0x011,
|
||||
PIXEvent_BeginEvent_OnContext_NoArgs = 0x012,
|
||||
PIXEvent_SetMarker_OnContext_VarArgs = 0x017,
|
||||
PIXEvent_SetMarker_OnContext_NoArgs = 0x018,
|
||||
};
|
||||
|
||||
static const UINT64 PIXEventsReservedRecordSpaceQwords = 64;
|
||||
static const UINT64 PIXEventsReservedTailSpaceQwords = 2;
|
||||
static const UINT64 PIXEventsSafeFastCopySpaceQwords = PIXEventsReservedRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
|
||||
static const UINT64 PIXEventsGraphicsRecordSpaceQwords = 64;
|
||||
|
||||
//Bits 7-19 (13 bits)
|
||||
static const UINT64 PIXEventsBlockEndMarker = 0x00000000000FFF80;
|
||||
|
||||
//Bits 10-19 (10 bits)
|
||||
static const UINT64 PIXEventsTypeReadMask = 0x00000000000FFC00;
|
||||
static const UINT64 PIXEventsTypeWriteMask = 0x00000000000003FF;
|
||||
static const UINT64 PIXEventsTypeBitShift = 10;
|
||||
|
||||
//Bits 20-63 (44 bits)
|
||||
static const UINT64 PIXEventsTimestampReadMask = 0xFFFFFFFFFFF00000;
|
||||
static const UINT64 PIXEventsTimestampWriteMask = 0x00000FFFFFFFFFFF;
|
||||
static const UINT64 PIXEventsTimestampBitShift = 20;
|
||||
|
||||
inline UINT64 PIXEncodeEventInfo(UINT64 timestamp, PIXEventType eventType)
|
||||
{
|
||||
return ((timestamp & PIXEventsTimestampWriteMask) << PIXEventsTimestampBitShift) |
|
||||
(((UINT64)eventType & PIXEventsTypeWriteMask) << PIXEventsTypeBitShift);
|
||||
}
|
||||
|
||||
//Bits 60-63 (4)
|
||||
static const UINT64 PIXEventsStringAlignmentWriteMask = 0x000000000000000F;
|
||||
static const UINT64 PIXEventsStringAlignmentReadMask = 0xF000000000000000;
|
||||
static const UINT64 PIXEventsStringAlignmentBitShift = 60;
|
||||
|
||||
//Bits 55-59 (5)
|
||||
static const UINT64 PIXEventsStringCopyChunkSizeWriteMask = 0x000000000000001F;
|
||||
static const UINT64 PIXEventsStringCopyChunkSizeReadMask = 0x0F80000000000000;
|
||||
static const UINT64 PIXEventsStringCopyChunkSizeBitShift = 55;
|
||||
|
||||
//Bit 54
|
||||
static const UINT64 PIXEventsStringIsANSIWriteMask = 0x0000000000000001;
|
||||
static const UINT64 PIXEventsStringIsANSIReadMask = 0x0040000000000000;
|
||||
static const UINT64 PIXEventsStringIsANSIBitShift = 54;
|
||||
|
||||
//Bit 53
|
||||
static const UINT64 PIXEventsStringIsShortcutWriteMask = 0x0000000000000001;
|
||||
static const UINT64 PIXEventsStringIsShortcutReadMask = 0x0020000000000000;
|
||||
static const UINT64 PIXEventsStringIsShortcutBitShift = 53;
|
||||
|
||||
inline UINT64 PIXEncodeStringInfo(UINT64 alignment, UINT64 copyChunkSize, BOOL isANSI, BOOL isShortcut)
|
||||
{
|
||||
return ((alignment & PIXEventsStringAlignmentWriteMask) << PIXEventsStringAlignmentBitShift) |
|
||||
((copyChunkSize & PIXEventsStringCopyChunkSizeWriteMask) << PIXEventsStringCopyChunkSizeBitShift) |
|
||||
(((UINT64)isANSI & PIXEventsStringIsANSIWriteMask) << PIXEventsStringIsANSIBitShift) |
|
||||
(((UINT64)isShortcut & PIXEventsStringIsShortcutWriteMask) << PIXEventsStringIsShortcutBitShift);
|
||||
}
|
||||
|
||||
template<UINT alignment, class T>
|
||||
inline bool PIXIsPointerAligned(T* pointer)
|
||||
{
|
||||
return !(((UINT64)pointer) & (alignment - 1));
|
||||
}
|
||||
|
||||
// Generic template version slower because of the additional clear write
|
||||
template<class T>
|
||||
inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, T argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*destination = 0ull;
|
||||
*((T*)destination) = argument;
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
// int32 specialization to avoid slower double memory writes
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<INT32>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT32 argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*reinterpret_cast<INT64*>(destination) = static_cast<INT64>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
// unsigned int32 specialization to avoid slower double memory writes
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<UINT32>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT32 argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*destination = static_cast<UINT64>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
// int64 specialization to avoid slower double memory writes
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<INT64>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT64 argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*reinterpret_cast<INT64*>(destination) = argument;
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
// unsigned int64 specialization to avoid slower double memory writes
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<UINT64>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT64 argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*destination = argument;
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
//floats must be cast to double during writing the data to be properly printed later when reading the data
|
||||
//this is needed because when float is passed to varargs function it's cast to double
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<float>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, float argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*reinterpret_cast<double*>(destination) = static_cast<double>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
//char has to be cast to a longer signed integer type
|
||||
//this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<char>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, char argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*reinterpret_cast<INT64*>(destination) = static_cast<INT64>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
//unsigned char has to be cast to a longer unsigned integer type
|
||||
//this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<unsigned char>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, unsigned char argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*destination = static_cast<UINT64>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
//bool has to be cast to an integer since it's not explicitly supported by string format routines
|
||||
//there's no format specifier for bool type, but it should work with integer format specifiers
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<bool>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, bool argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
*destination = static_cast<UINT64>(argument);
|
||||
++destination;
|
||||
}
|
||||
}
|
||||
|
||||
inline void PIXCopyEventArgumentSlowest(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
|
||||
{
|
||||
*destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE);
|
||||
while (destination < limit)
|
||||
{
|
||||
UINT64 c = static_cast<uint8_t>(argument[0]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = 0;
|
||||
return;
|
||||
}
|
||||
UINT64 x = c;
|
||||
c = static_cast<uint8_t>(argument[1]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 8;
|
||||
c = static_cast<uint8_t>(argument[2]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 16;
|
||||
c = static_cast<uint8_t>(argument[3]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 24;
|
||||
c = static_cast<uint8_t>(argument[4]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 32;
|
||||
c = static_cast<uint8_t>(argument[5]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 40;
|
||||
c = static_cast<uint8_t>(argument[6]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 48;
|
||||
c = static_cast<uint8_t>(argument[7]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 56;
|
||||
*destination++ = x;
|
||||
argument += 8;
|
||||
}
|
||||
}
|
||||
|
||||
inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
|
||||
{
|
||||
#if PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
if (PIXIsPointerAligned<8>(argument))
|
||||
{
|
||||
*destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE);
|
||||
UINT64* source = (UINT64*)argument;
|
||||
while (destination < limit)
|
||||
{
|
||||
UINT64 qword = *source++;
|
||||
*destination++ = qword;
|
||||
//check if any of the characters is a terminating zero
|
||||
if (!((qword & 0xFF00000000000000) &&
|
||||
(qword & 0xFF000000000000) &&
|
||||
(qword & 0xFF0000000000) &&
|
||||
(qword & 0xFF00000000) &&
|
||||
(qword & 0xFF000000) &&
|
||||
(qword & 0xFF0000) &&
|
||||
(qword & 0xFF00) &&
|
||||
(qword & 0xFF)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
{
|
||||
PIXCopyEventArgumentSlowest(destination, limit, argument);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<PCSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
if (argument != nullptr)
|
||||
{
|
||||
#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
if (PIXIsPointerAligned<16>(argument))
|
||||
{
|
||||
*destination++ = PIXEncodeStringInfo(0, 16, TRUE, FALSE);
|
||||
__m128i zero = _mm_setzero_si128();
|
||||
if (PIXIsPointerAligned<16>(destination))
|
||||
{
|
||||
while (destination < limit)
|
||||
{
|
||||
__m128i mem = _mm_load_si128((__m128i*)argument);
|
||||
_mm_store_si128((__m128i*)destination, mem);
|
||||
//check if any of the characters is a terminating zero
|
||||
__m128i res = _mm_cmpeq_epi8(mem, zero);
|
||||
destination += 2;
|
||||
if (_mm_movemask_epi8(res))
|
||||
break;
|
||||
argument += 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (destination < limit)
|
||||
{
|
||||
__m128i mem = _mm_load_si128((__m128i*)argument);
|
||||
_mm_storeu_si128((__m128i*)destination, mem);
|
||||
//check if any of the characters is a terminating zero
|
||||
__m128i res = _mm_cmpeq_epi8(mem, zero);
|
||||
destination += 2;
|
||||
if (_mm_movemask_epi8(res))
|
||||
break;
|
||||
argument += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
{
|
||||
PIXCopyEventArgumentSlow(destination, limit, argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*destination++ = 0ull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<PSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PSTR argument)
|
||||
{
|
||||
PIXCopyEventArgument(destination, limit, (PCSTR)argument);
|
||||
}
|
||||
|
||||
inline void PIXCopyEventArgumentSlowest(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
|
||||
{
|
||||
*destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE);
|
||||
while (destination < limit)
|
||||
{
|
||||
UINT64 c = static_cast<uint16_t>(argument[0]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = 0;
|
||||
return;
|
||||
}
|
||||
UINT64 x = c;
|
||||
c = static_cast<uint16_t>(argument[1]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 16;
|
||||
c = static_cast<uint16_t>(argument[2]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 32;
|
||||
c = static_cast<uint16_t>(argument[3]);
|
||||
if (!c)
|
||||
{
|
||||
*destination++ = x;
|
||||
return;
|
||||
}
|
||||
x |= c << 48;
|
||||
*destination++ = x;
|
||||
argument += 4;
|
||||
}
|
||||
}
|
||||
|
||||
inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
|
||||
{
|
||||
#if PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
if (PIXIsPointerAligned<8>(argument))
|
||||
{
|
||||
*destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE);
|
||||
UINT64* source = (UINT64*)argument;
|
||||
while (destination < limit)
|
||||
{
|
||||
UINT64 qword = *source++;
|
||||
*destination++ = qword;
|
||||
//check if any of the characters is a terminating zero
|
||||
//TODO: check if reversed condition is faster
|
||||
if (!((qword & 0xFFFF000000000000) &&
|
||||
(qword & 0xFFFF00000000) &&
|
||||
(qword & 0xFFFF0000) &&
|
||||
(qword & 0xFFFF)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
{
|
||||
PIXCopyEventArgumentSlowest(destination, limit, argument);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void PIXCopyEventArgument<PCWSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
|
||||
{
|
||||
if (destination < limit)
|
||||
{
|
||||
if (argument != nullptr)
|
||||
{
|
||||
#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
if (PIXIsPointerAligned<16>(argument))
|
||||
{
|
||||
*destination++ = PIXEncodeStringInfo(0, 16, FALSE, FALSE);
|
||||
__m128i zero = _mm_setzero_si128();
|
||||
if (PIXIsPointerAligned<16>(destination))
|
||||
{
|
||||
while (destination < limit)
|
||||
{
|
||||
__m128i mem = _mm_load_si128((__m128i*)argument);
|
||||
_mm_store_si128((__m128i*)destination, mem);
|
||||
//check if any of the characters is a terminating zero
|
||||
__m128i res = _mm_cmpeq_epi16(mem, zero);
|
||||
destination += 2;
|
||||
if (_mm_movemask_epi8(res))
|
||||
break;
|
||||
argument += 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (destination < limit)
|
||||
{
|
||||
__m128i mem = _mm_load_si128((__m128i*)argument);
|
||||
_mm_storeu_si128((__m128i*)destination, mem);
|
||||
//check if any of the characters is a terminating zero
|
||||
__m128i res = _mm_cmpeq_epi16(mem, zero);
|
||||
destination += 2;
|
||||
if (_mm_movemask_epi8(res))
|
||||
break;
|
||||
argument += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
|
||||
{
|
||||
PIXCopyEventArgumentSlow(destination, limit, argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*destination++ = 0ull;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit)
|
||||
{
|
||||
// nothing
|
||||
UNREFERENCED_PARAMETER(destination);
|
||||
UNREFERENCED_PARAMETER(limit);
|
||||
}
|
||||
|
||||
template<typename ARG, typename... ARGS>
|
||||
void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, ARG const& arg, ARGS const&... args)
|
||||
{
|
||||
PIXCopyEventArgument(destination, limit, arg);
|
||||
PIXCopyEventArguments(destination, limit, args...);
|
||||
}
|
||||
|
||||
template<typename... ARGS>
|
||||
struct PIXEventTypeInferer
|
||||
{
|
||||
static constexpr PIXEventType Begin() { return PIXEvent_BeginEvent_VarArgs; }
|
||||
static constexpr PIXEventType SetMarker() { return PIXEvent_SetMarker_VarArgs; }
|
||||
static constexpr PIXEventType BeginOnContext() { return PIXEvent_BeginEvent_OnContext_VarArgs; }
|
||||
static constexpr PIXEventType SetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_VarArgs; }
|
||||
static constexpr PIXEventType End() { return PIXEvent_EndEvent; }
|
||||
|
||||
// Xbox and Windows store different types of events for context events.
|
||||
// On Xbox these include a context argument, while on Windows they do
|
||||
// not. It is important not to change the event types used on the
|
||||
// Windows version as there are OS components (eg debug layer & DRED)
|
||||
// that decode event structs.
|
||||
#ifdef PIX_XBOX
|
||||
static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_VarArgs; }
|
||||
static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_VarArgs; }
|
||||
static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent_OnContext; }
|
||||
#else
|
||||
static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_VarArgs; }
|
||||
static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_VarArgs; }
|
||||
static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent; }
|
||||
#endif
|
||||
};
|
||||
|
||||
template<>
|
||||
struct PIXEventTypeInferer<>
|
||||
{
|
||||
static constexpr PIXEventType Begin() { return PIXEvent_BeginEvent_NoArgs; }
|
||||
static constexpr PIXEventType SetMarker() { return PIXEvent_SetMarker_NoArgs; }
|
||||
static constexpr PIXEventType BeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; }
|
||||
static constexpr PIXEventType SetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; }
|
||||
static constexpr PIXEventType End() { return PIXEvent_EndEvent; }
|
||||
|
||||
#ifdef PIX_XBOX
|
||||
static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; }
|
||||
static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; }
|
||||
static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent_OnContext; }
|
||||
#else
|
||||
static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_NoArgs; }
|
||||
static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_NoArgs; }
|
||||
static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent; }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
template<size_t size, typename STR, typename... ARGS>
|
||||
UINT64* EncodeBeginEventForContext(UINT64 (&buffer)[size], UINT64 color, STR formatString, ARGS... args)
|
||||
{
|
||||
UINT64* destination = buffer;
|
||||
UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
|
||||
|
||||
*destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer<ARGS...>::GpuBeginOnContext());
|
||||
*destination++ = color;
|
||||
|
||||
PIXCopyEventArguments(destination, limit, formatString, args...);
|
||||
*destination = 0ull;
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
template<size_t size, typename STR, typename... ARGS>
|
||||
UINT64* EncodeSetMarkerForContext(UINT64 (&buffer)[size], UINT64 color, STR formatString, ARGS... args)
|
||||
{
|
||||
UINT64* destination = buffer;
|
||||
UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
|
||||
|
||||
*destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer<ARGS...>::GpuSetMarkerOnContext());
|
||||
*destination++ = color;
|
||||
|
||||
PIXCopyEventArguments(destination, limit, formatString, args...);
|
||||
*destination = 0ull;
|
||||
|
||||
return destination;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //_PIXEventsLegacy_H_
|
||||
@ -0,0 +1,195 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _PIX3_H_
|
||||
#define _PIX3_H_
|
||||
|
||||
#include <sal.h>
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error "Only C++ files can include pix3.h. C is not supported."
|
||||
#endif
|
||||
|
||||
#if !defined(USE_PIX_SUPPORTED_ARCHITECTURE)
|
||||
#if defined(_M_X64) || defined(USE_PIX_ON_ALL_ARCHITECTURES) || defined(_M_ARM64)
|
||||
#define USE_PIX_SUPPORTED_ARCHITECTURE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(USE_PIX)
|
||||
#if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && (defined(_DEBUG) || DBG || defined(PROFILE) || defined(PROFILE_BUILD)) && !defined(_PREFAST_)
|
||||
#define USE_PIX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(USE_PIX) && !defined(USE_PIX_SUPPORTED_ARCHITECTURE)
|
||||
#pragma message("Warning: Pix markers are only supported on AMD64 and ARM64")
|
||||
#endif
|
||||
|
||||
|
||||
// These flags are used by both PIXBeginCapture and PIXGetCaptureState
|
||||
#define PIX_CAPTURE_TIMING (1 << 0)
|
||||
#define PIX_CAPTURE_GPU (1 << 1)
|
||||
#define PIX_CAPTURE_FUNCTION_SUMMARY (1 << 2)
|
||||
#define PIX_CAPTURE_FUNCTION_DETAILS (1 << 3)
|
||||
#define PIX_CAPTURE_CALLGRAPH (1 << 4)
|
||||
#define PIX_CAPTURE_INSTRUCTION_TRACE (1 << 5)
|
||||
#define PIX_CAPTURE_SYSTEM_MONITOR_COUNTERS (1 << 6)
|
||||
#define PIX_CAPTURE_VIDEO (1 << 7)
|
||||
#define PIX_CAPTURE_AUDIO (1 << 8)
|
||||
#define PIX_CAPTURE_GPU_TRACE (1 << 9)
|
||||
#define PIX_CAPTURE_RESERVED (1 << 15)
|
||||
|
||||
union PIXCaptureParameters
|
||||
{
|
||||
enum PIXCaptureStorage
|
||||
{
|
||||
Memory = 0,
|
||||
MemoryCircular = 1, // Xbox only
|
||||
FileCircular = 2, // PC only
|
||||
};
|
||||
|
||||
struct GpuCaptureParameters
|
||||
{
|
||||
PCWSTR FileName;
|
||||
} GpuCaptureParameters;
|
||||
|
||||
struct TimingCaptureParameters
|
||||
{
|
||||
PCWSTR FileName;
|
||||
UINT32 MaximumToolingMemorySizeMb;
|
||||
PIXCaptureStorage CaptureStorage;
|
||||
|
||||
BOOL CaptureGpuTiming;
|
||||
|
||||
BOOL CaptureCallstacks;
|
||||
BOOL CaptureCpuSamples;
|
||||
UINT32 CpuSamplesPerSecond;
|
||||
|
||||
BOOL CaptureFileIO;
|
||||
|
||||
BOOL CaptureVirtualAllocEvents;
|
||||
BOOL CaptureHeapAllocEvents;
|
||||
BOOL CaptureXMemEvents; // Xbox only
|
||||
BOOL CapturePixMemEvents;
|
||||
BOOL CapturePageFaultEvents;
|
||||
BOOL CaptureVideoFrames; // Xbox only
|
||||
} TimingCaptureParameters;
|
||||
|
||||
struct GpuTraceParameters // Xbox Series and newer only
|
||||
{
|
||||
PWSTR FileName;
|
||||
UINT32 MaximumToolingMemorySizeMb;
|
||||
|
||||
BOOL CaptureGpuOccupancy;
|
||||
|
||||
} GpuTraceParameters;
|
||||
};
|
||||
|
||||
typedef PIXCaptureParameters* PPIXCaptureParameters;
|
||||
|
||||
#if defined(XBOX) || defined(_XBOX_ONE) || defined(_DURANGO) || defined(_GAMING_XBOX) || defined(_GAMING_XBOX_SCARLETT)
|
||||
#include "pix3_xbox.h"
|
||||
#else
|
||||
#include "pix3_win.h"
|
||||
#endif
|
||||
|
||||
#if defined(XBOX) || defined(_XBOX_ONE) || defined(_DURANGO) || defined(_GAMING_XBOX) || defined(_GAMING_XBOX_SCARLETT)
|
||||
#define PIX_XBOX
|
||||
#if defined(_GAMING_XBOX) || defined(_GAMING_XBOX_SCARLETT)
|
||||
#define PIX_GAMING_XBOX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(PIX_USE_GPU_MARKERS_V2)
|
||||
#ifdef PIX_GAMING_XBOX
|
||||
#define PIX_USE_GPU_MARKERS_V2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && (defined(USE_PIX) || defined(USE_PIX_RETAIL))
|
||||
|
||||
#define PIX_EVENTS_ARE_TURNED_ON
|
||||
|
||||
#include "PIXEventsCommon.h"
|
||||
#include "PIXEvents.h"
|
||||
|
||||
#ifdef USE_PIX
|
||||
// Starts a programmatically controlled capture.
|
||||
// captureFlags uses the PIX_CAPTURE_* family of flags to specify the type of capture to take
|
||||
extern "C" HRESULT WINAPI PIXBeginCapture2(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters);
|
||||
inline HRESULT PIXBeginCapture(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters) { return PIXBeginCapture2(captureFlags, captureParameters); }
|
||||
|
||||
// Stops a programmatically controlled capture
|
||||
// If discard == TRUE, the captured data is discarded
|
||||
// If discard == FALSE, the captured data is saved
|
||||
// discard parameter is not supported on Windows
|
||||
extern "C" HRESULT WINAPI PIXEndCapture(BOOL discard);
|
||||
|
||||
extern "C" DWORD WINAPI PIXGetCaptureState();
|
||||
|
||||
extern "C" void WINAPI PIXReportCounter(_In_ PCWSTR name, float value);
|
||||
|
||||
#endif // USE_PIX
|
||||
|
||||
#endif // (USE_PIX_SUPPORTED_ARCHITECTURE) && (USE_PIX || USE_PIX_RETAIL)
|
||||
|
||||
#if !defined(USE_PIX_SUPPORTED_ARCHITECTURE) || !defined(USE_PIX)
|
||||
|
||||
// Eliminate these APIs when not using PIX
|
||||
inline HRESULT PIXBeginCapture2(DWORD, _In_opt_ const PIXCaptureParameters*) { return S_OK; }
|
||||
inline HRESULT PIXBeginCapture(DWORD, _In_opt_ const PIXCaptureParameters*) { return S_OK; }
|
||||
inline HRESULT PIXEndCapture(BOOL) { return S_OK; }
|
||||
inline HRESULT PIXGpuCaptureNextFrames(PCWSTR, UINT32) { return S_OK; }
|
||||
inline HRESULT PIXSetTargetWindow(HWND) { return S_OK; }
|
||||
inline HRESULT PIXForceD3D11On12() { return S_OK; }
|
||||
inline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions) { return S_OK; }
|
||||
inline bool WINAPI PIXIsAttachedForGpuCapture() { return false; }
|
||||
inline HINSTANCE WINAPI PIXOpenCaptureInUI(PCWSTR) { return 0; }
|
||||
inline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary() { return nullptr; }
|
||||
inline HMODULE PIXLoadLatestWinPixTimingCapturerLibrary() { return nullptr; }
|
||||
inline DWORD PIXGetCaptureState() { return 0; }
|
||||
inline void PIXReportCounter(_In_ PCWSTR, float) {}
|
||||
inline void PIXNotifyWakeFromFenceSignal(_In_ HANDLE) {}
|
||||
|
||||
#if !defined(USE_PIX_RETAIL)
|
||||
|
||||
inline void PIXBeginEvent(UINT64, _In_ PCSTR, ...) {}
|
||||
inline void PIXBeginEvent(UINT64, _In_ PCWSTR, ...) {}
|
||||
inline void PIXBeginEvent(void*, UINT64, _In_ PCSTR, ...) {}
|
||||
inline void PIXBeginEvent(void*, UINT64, _In_ PCWSTR, ...) {}
|
||||
inline void PIXEndEvent() {}
|
||||
inline void PIXEndEvent(void*) {}
|
||||
inline void PIXSetMarker(UINT64, _In_ PCSTR, ...) {}
|
||||
inline void PIXSetMarker(UINT64, _In_ PCWSTR, ...) {}
|
||||
inline void PIXSetMarker(void*, UINT64, _In_ PCSTR, ...) {}
|
||||
inline void PIXSetMarker(void*, UINT64, _In_ PCWSTR, ...) {}
|
||||
inline void PIXBeginRetailEvent(void*, UINT64, _In_ PCSTR, ...) {}
|
||||
inline void PIXBeginRetailEvent(void*, UINT64, _In_ PCWSTR, ...) {}
|
||||
inline void PIXEndRetailEvent(void*) {}
|
||||
inline void PIXSetRetailMarker(void*, UINT64, _In_ PCSTR, ...) {}
|
||||
inline void PIXSetRetailMarker(void*, UINT64, _In_ PCWSTR, ...) {}
|
||||
inline void PIXScopedEvent(UINT64, _In_ PCSTR, ...) {}
|
||||
inline void PIXScopedEvent(UINT64, _In_ PCWSTR, ...) {}
|
||||
inline void PIXScopedEvent(void*, UINT64, _In_ PCSTR, ...) {}
|
||||
inline void PIXScopedEvent(void*, UINT64, _In_ PCWSTR, ...) {}
|
||||
|
||||
#endif // !USE_PIX_RETAIL
|
||||
|
||||
// don't show warnings about expressions with no effect
|
||||
#pragma warning(disable:4548)
|
||||
#pragma warning(disable:4555)
|
||||
|
||||
#endif // !USE_PIX_SUPPORTED_ARCHITECTURE || !USE_PIX
|
||||
|
||||
// Use these functions to specify colors to pass as metadata to a PIX event/marker API.
|
||||
// Use PIX_COLOR() to specify a particular color for an event.
|
||||
// Or, use PIX_COLOR_INDEX() to specify a set of unique event categories, and let PIX choose
|
||||
// the colors to represent each category.
|
||||
inline UINT32 PIX_COLOR(UINT8 r, UINT8 g, UINT8 b) { return 0xff000000u | ((UINT32)r << 16) | ((UINT32)g << 8) | (UINT32)b; }
|
||||
inline UINT8 PIX_COLOR_INDEX(UINT8 i) { return i; }
|
||||
const UINT8 PIX_COLOR_DEFAULT = PIX_COLOR_INDEX(0);
|
||||
|
||||
#endif // _PIX3_H_
|
||||
@ -0,0 +1,509 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// Don't include this file directly - use pix3.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _PIX3_H_
|
||||
#error Don't include this file directly - use pix3.h
|
||||
#endif
|
||||
|
||||
#ifndef _PIX3_WIN_H_
|
||||
#define _PIX3_WIN_H_
|
||||
|
||||
// PIXEventsThreadInfo is defined in PIXEventsCommon.h
|
||||
struct PIXEventsThreadInfo;
|
||||
|
||||
extern "C" PIXEventsThreadInfo* WINAPI PIXGetThreadInfo() noexcept;
|
||||
|
||||
#if defined(USE_PIX) && defined(USE_PIX_SUPPORTED_ARCHITECTURE)
|
||||
// Notifies PIX that an event handle was set as a result of a D3D12 fence being signaled.
|
||||
// The event specified must have the same handle value as the handle
|
||||
// used in ID3D12Fence::SetEventOnCompletion.
|
||||
extern "C" void WINAPI PIXNotifyWakeFromFenceSignal(_In_ HANDLE event);
|
||||
|
||||
// Notifies PIX that a block of memory was allocated
|
||||
extern "C" void WINAPI PIXRecordMemoryAllocationEvent(USHORT allocatorId, void* baseAddress, size_t size, UINT64 metadata);
|
||||
|
||||
// Notifies PIX that a block of memory was freed
|
||||
extern "C" void WINAPI PIXRecordMemoryFreeEvent(USHORT allocatorId, void* baseAddress, size_t size, UINT64 metadata);
|
||||
|
||||
#else
|
||||
|
||||
// Eliminate these APIs when not using PIX
|
||||
inline void PIXRecordMemoryAllocationEvent(USHORT, void*, size_t, UINT64) {}
|
||||
inline void PIXRecordMemoryFreeEvent(USHORT, void*, size_t, UINT64) {}
|
||||
|
||||
#endif
|
||||
|
||||
// The following WINPIX_EVENT_* defines denote the different metadata values that have
|
||||
// been used by tools to denote how to parse pix marker event data. The first two values
|
||||
// are legacy values used by pix.h in the Windows SDK.
|
||||
#define WINPIX_EVENT_UNICODE_VERSION 0
|
||||
#define WINPIX_EVENT_ANSI_VERSION 1
|
||||
|
||||
// These values denote PIX marker event data that was created by the WinPixEventRuntime.
|
||||
// In early 2023 we revised the PIX marker format and defined a new version number.
|
||||
#define WINPIX_EVENT_PIX3BLOB_VERSION 2
|
||||
#define WINPIX_EVENT_PIX3BLOB_V2 6345127 // A number that other applications are unlikely to have used before
|
||||
|
||||
// For backcompat reasons, the WinPixEventRuntime uses the older PIX3BLOB format when it passes data
|
||||
// into the D3D12 runtime. It will be updated to use the V2 format in the future.
|
||||
#define D3D12_EVENT_METADATA WINPIX_EVENT_PIX3BLOB_VERSION
|
||||
|
||||
__forceinline UINT64 PIXGetTimestampCounter()
|
||||
{
|
||||
LARGE_INTEGER time = {};
|
||||
QueryPerformanceCounter(&time);
|
||||
return static_cast<UINT64>(time.QuadPart);
|
||||
}
|
||||
|
||||
enum PIXHUDOptions
|
||||
{
|
||||
PIX_HUD_SHOW_ON_ALL_WINDOWS = 0x1,
|
||||
PIX_HUD_SHOW_ON_TARGET_WINDOW_ONLY = 0x2,
|
||||
PIX_HUD_SHOW_ON_NO_WINDOWS = 0x4
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(PIXHUDOptions);
|
||||
|
||||
#if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && defined(USE_PIX)
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)
|
||||
|
||||
#include <shlobj.h>
|
||||
#include <strsafe.h>
|
||||
#include <knownfolders.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#define PIXERRORCHECK(value) do { \
|
||||
if (FAILED(value)) \
|
||||
return nullptr; \
|
||||
} while(0)
|
||||
|
||||
namespace PixImpl
|
||||
{
|
||||
#ifndef PIX3_WIN_UNIT_TEST
|
||||
|
||||
__forceinline BOOL GetModuleHandleExW(
|
||||
DWORD dwFlags,
|
||||
LPCWSTR lpModuleName,
|
||||
HMODULE* phModule)
|
||||
{
|
||||
return ::GetModuleHandleExW(dwFlags, lpModuleName, phModule);
|
||||
}
|
||||
|
||||
__forceinline HRESULT SHGetKnownFolderPath(
|
||||
REFKNOWNFOLDERID rfid,
|
||||
DWORD dwFlags,
|
||||
HANDLE hToken,
|
||||
PWSTR* ppszPath)
|
||||
{
|
||||
return ::SHGetKnownFolderPath(rfid, dwFlags, hToken, ppszPath);
|
||||
}
|
||||
|
||||
__forceinline void CoTaskMemFree(LPVOID pv)
|
||||
{
|
||||
return ::CoTaskMemFree(pv);
|
||||
}
|
||||
|
||||
__forceinline HANDLE FindFirstFileW(
|
||||
LPCWSTR lpFileName,
|
||||
LPWIN32_FIND_DATAW lpFindFileData)
|
||||
{
|
||||
return ::FindFirstFileW(lpFileName, lpFindFileData);
|
||||
}
|
||||
|
||||
__forceinline DWORD GetFileAttributesW(LPCWSTR lpFileName)
|
||||
{
|
||||
return ::GetFileAttributesW(lpFileName);
|
||||
}
|
||||
|
||||
__forceinline BOOL FindNextFileW(
|
||||
HANDLE hFindFile,
|
||||
LPWIN32_FIND_DATAW lpFindFileData)
|
||||
{
|
||||
return ::FindNextFileW(hFindFile, lpFindFileData);
|
||||
}
|
||||
|
||||
__forceinline BOOL FindClose(HANDLE hFindFile)
|
||||
{
|
||||
return ::FindClose(hFindFile);
|
||||
}
|
||||
|
||||
__forceinline HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, DWORD flags)
|
||||
{
|
||||
return ::LoadLibraryExW(lpLibFileName, NULL, flags);
|
||||
}
|
||||
|
||||
#endif // !PIX3_WIN_UNIT_TESTS
|
||||
|
||||
__forceinline void * GetGpuCaptureFunctionPtr(LPCSTR fnName) noexcept
|
||||
{
|
||||
HMODULE module = GetModuleHandleW(L"WinPixGpuCapturer.dll");
|
||||
if (module == NULL)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto fn = (void*)GetProcAddress(module, fnName);
|
||||
if (fn == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
__forceinline void* GetTimingCaptureFunctionPtr(LPCSTR fnName) noexcept
|
||||
{
|
||||
HMODULE module = GetModuleHandleW(L"WinPixTimingCapturer.dll");
|
||||
if (module == NULL)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto fn = (void*)GetProcAddress(module, fnName);
|
||||
if (fn == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
__forceinline HMODULE PIXLoadLatestCapturerLibrary(wchar_t const* capturerDllName, DWORD flags)
|
||||
{
|
||||
HMODULE libHandle{};
|
||||
|
||||
if (PixImpl::GetModuleHandleExW(0, capturerDllName, &libHandle))
|
||||
{
|
||||
return libHandle;
|
||||
}
|
||||
|
||||
LPWSTR programFilesPath = nullptr;
|
||||
if (FAILED(PixImpl::SHGetKnownFolderPath(FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, NULL, &programFilesPath)))
|
||||
{
|
||||
PixImpl::CoTaskMemFree(programFilesPath);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wchar_t pixSearchPath[MAX_PATH];
|
||||
|
||||
if (FAILED(StringCchCopyW(pixSearchPath, MAX_PATH, programFilesPath)))
|
||||
{
|
||||
PixImpl::CoTaskMemFree(programFilesPath);
|
||||
return nullptr;
|
||||
}
|
||||
PixImpl::CoTaskMemFree(programFilesPath);
|
||||
|
||||
PIXERRORCHECK(StringCchCatW(pixSearchPath, MAX_PATH, L"\\Microsoft PIX\\*"));
|
||||
|
||||
WIN32_FIND_DATAW findData;
|
||||
bool foundPixInstallation = false;
|
||||
wchar_t newestVersionFound[MAX_PATH];
|
||||
wchar_t output[MAX_PATH];
|
||||
wchar_t possibleOutput[MAX_PATH];
|
||||
|
||||
HANDLE hFind = PixImpl::FindFirstFileW(pixSearchPath, &findData);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
(findData.cFileName[0] != '.'))
|
||||
{
|
||||
if (!foundPixInstallation || wcscmp(newestVersionFound, findData.cFileName) <= 0)
|
||||
{
|
||||
// length - 1 to get rid of the wildcard character in the search path
|
||||
PIXERRORCHECK(StringCchCopyNW(possibleOutput, MAX_PATH, pixSearchPath, wcslen(pixSearchPath) - 1));
|
||||
PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, findData.cFileName));
|
||||
PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, L"\\"));
|
||||
PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, capturerDllName));
|
||||
|
||||
DWORD result = PixImpl::GetFileAttributesW(possibleOutput);
|
||||
|
||||
if (result != INVALID_FILE_ATTRIBUTES && !(result & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
foundPixInstallation = true;
|
||||
PIXERRORCHECK(StringCchCopyW(newestVersionFound, _countof(newestVersionFound), findData.cFileName));
|
||||
PIXERRORCHECK(StringCchCopyW(output, _countof(possibleOutput), possibleOutput));
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (PixImpl::FindNextFileW(hFind, &findData) != 0);
|
||||
}
|
||||
|
||||
PixImpl::FindClose(hFind);
|
||||
|
||||
if (!foundPixInstallation)
|
||||
{
|
||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return PixImpl::LoadLibraryExW(output, flags);
|
||||
}
|
||||
}
|
||||
|
||||
#undef PIXERRORCHECK
|
||||
|
||||
__forceinline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary()
|
||||
{
|
||||
return PixImpl::PIXLoadLatestCapturerLibrary(
|
||||
L"WinPixGpuCapturer.dll",
|
||||
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
|
||||
}
|
||||
|
||||
__forceinline HMODULE PIXLoadLatestWinPixTimingCapturerLibrary()
|
||||
{
|
||||
return PixImpl::PIXLoadLatestCapturerLibrary(
|
||||
L"WinPixTimingCapturer.dll",
|
||||
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
|
||||
}
|
||||
|
||||
__forceinline HRESULT WINAPI PIXSetTargetWindow(HWND hwnd)
|
||||
{
|
||||
typedef void(WINAPI* SetGlobalTargetWindowFn)(HWND);
|
||||
|
||||
auto fn = (SetGlobalTargetWindowFn)PixImpl::GetGpuCaptureFunctionPtr("SetGlobalTargetWindow");
|
||||
if (fn == nullptr)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
fn(hwnd);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
__forceinline HRESULT WINAPI PIXGpuCaptureNextFrames(PCWSTR fileName, UINT32 numFrames)
|
||||
{
|
||||
typedef HRESULT(WINAPI* CaptureNextFrameFn)(PCWSTR, UINT32);
|
||||
|
||||
auto fn = (CaptureNextFrameFn)PixImpl::GetGpuCaptureFunctionPtr("CaptureNextFrame");
|
||||
if (fn == nullptr)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
return fn(fileName, numFrames);
|
||||
}
|
||||
|
||||
extern "C" __forceinline HRESULT WINAPI PIXBeginCapture2(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters)
|
||||
{
|
||||
if (captureFlags == PIX_CAPTURE_GPU)
|
||||
{
|
||||
typedef HRESULT(WINAPI* BeginProgrammaticGpuCaptureFn)(const PPIXCaptureParameters);
|
||||
|
||||
auto fn = (BeginProgrammaticGpuCaptureFn)PixImpl::GetGpuCaptureFunctionPtr("BeginProgrammaticGpuCapture");
|
||||
if (fn == nullptr)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
return fn(captureParameters);
|
||||
}
|
||||
else if (captureFlags == PIX_CAPTURE_TIMING)
|
||||
{
|
||||
typedef HRESULT(WINAPI* BeginProgrammaticTimingCaptureFn)(void const*, UINT64);
|
||||
|
||||
auto fn = (BeginProgrammaticTimingCaptureFn)PixImpl::GetTimingCaptureFunctionPtr("BeginProgrammaticTimingCapture");
|
||||
if (fn == nullptr)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
return fn(&captureParameters->TimingCaptureParameters, sizeof(captureParameters->TimingCaptureParameters));
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" __forceinline HRESULT WINAPI PIXEndCapture(BOOL discard)
|
||||
{
|
||||
// We can't tell if the user wants to end a GPU Capture or a Timing Capture.
|
||||
// The user shouldn't have both WinPixGpuCapturer and WinPixTimingCapturer loaded in the process though,
|
||||
// so we can just look for one of them and call it.
|
||||
typedef HRESULT(WINAPI* EndProgrammaticGpuCaptureFn)(void);
|
||||
auto gpuFn = (EndProgrammaticGpuCaptureFn)PixImpl::GetGpuCaptureFunctionPtr("EndProgrammaticGpuCapture");
|
||||
if (gpuFn != NULL)
|
||||
{
|
||||
return gpuFn();
|
||||
}
|
||||
|
||||
typedef HRESULT(WINAPI* EndProgrammaticTimingCaptureFn)(BOOL);
|
||||
auto timingFn = (EndProgrammaticTimingCaptureFn)PixImpl::GetTimingCaptureFunctionPtr("EndProgrammaticTimingCapture");
|
||||
if (timingFn != NULL)
|
||||
{
|
||||
return timingFn(discard);
|
||||
}
|
||||
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
__forceinline HRESULT WINAPI PIXForceD3D11On12()
|
||||
{
|
||||
typedef HRESULT (WINAPI* ForceD3D11On12Fn)(void);
|
||||
|
||||
auto fn = (ForceD3D11On12Fn)PixImpl::GetGpuCaptureFunctionPtr("ForceD3D11On12");
|
||||
if (fn == NULL)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
return fn();
|
||||
}
|
||||
|
||||
__forceinline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions hudOptions)
|
||||
{
|
||||
typedef HRESULT(WINAPI* SetHUDOptionsFn)(PIXHUDOptions);
|
||||
|
||||
auto fn = (SetHUDOptionsFn)PixImpl::GetGpuCaptureFunctionPtr("SetHUDOptions");
|
||||
if (fn == NULL)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
return fn(hudOptions);
|
||||
}
|
||||
|
||||
__forceinline bool WINAPI PIXIsAttachedForGpuCapture()
|
||||
{
|
||||
typedef bool(WINAPI* GetIsAttachedToPixFn)(void);
|
||||
auto fn = (GetIsAttachedToPixFn)PixImpl::GetGpuCaptureFunctionPtr("GetIsAttachedToPix");
|
||||
if (fn == NULL)
|
||||
{
|
||||
OutputDebugStringW(L"WinPixEventRuntime error: Mismatched header/dll. Please ensure that pix3.h and WinPixGpuCapturer.dll match");
|
||||
return false;
|
||||
}
|
||||
|
||||
return fn();
|
||||
}
|
||||
|
||||
__forceinline HINSTANCE WINAPI PIXOpenCaptureInUI(PCWSTR fileName)
|
||||
{
|
||||
return ShellExecuteW(0, 0, fileName, 0, 0, SW_SHOW);
|
||||
}
|
||||
|
||||
#else
|
||||
__forceinline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
__forceinline HMODULE PIXLoadLatestWinPixTimingCapturerLibrary()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
__forceinline HRESULT WINAPI PIXSetTargetWindow(HWND)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
__forceinline HRESULT WINAPI PIXGpuCaptureNextFrames(PCWSTR, UINT32)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
extern "C" __forceinline HRESULT WINAPI PIXBeginCapture2(DWORD, _In_opt_ const PPIXCaptureParameters)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
extern "C" __forceinline HRESULT WINAPI PIXEndCapture(BOOL)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
__forceinline HRESULT WINAPI PIXForceD3D11On12()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
__forceinline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
__forceinline bool WINAPI PIXIsAttachedForGpuCapture()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
__forceinline HINSTANCE WINAPI PIXOpenCaptureInUI(PCWSTR)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif // WINAPI_PARTITION
|
||||
|
||||
#endif // USE_PIX_SUPPORTED_ARCHITECTURE || USE_PIX
|
||||
|
||||
#if defined(__d3d12_h__)
|
||||
|
||||
inline void PIXInsertTimingMarkerOnContextForBeginEvent(_In_ ID3D12GraphicsCommandList* commandList, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(eventType);
|
||||
commandList->BeginEvent(WINPIX_EVENT_PIX3BLOB_V2, data, size);
|
||||
}
|
||||
|
||||
inline void PIXInsertTimingMarkerOnContextForBeginEvent(_In_ ID3D12CommandQueue* commandQueue, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(eventType);
|
||||
commandQueue->BeginEvent(WINPIX_EVENT_PIX3BLOB_V2, data, size);
|
||||
}
|
||||
|
||||
inline void PIXInsertTimingMarkerOnContextForSetMarker(_In_ ID3D12GraphicsCommandList* commandList, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(eventType);
|
||||
commandList->SetMarker(WINPIX_EVENT_PIX3BLOB_V2, data, size);
|
||||
}
|
||||
|
||||
inline void PIXInsertTimingMarkerOnContextForSetMarker(_In_ ID3D12CommandQueue* commandQueue, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(eventType);
|
||||
commandQueue->SetMarker(WINPIX_EVENT_PIX3BLOB_V2, data, size);
|
||||
}
|
||||
|
||||
inline void PIXInsertTimingMarkerOnContextForEndEvent(_In_ ID3D12GraphicsCommandList* commandList, UINT8 eventType)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(eventType);
|
||||
commandList->EndEvent();
|
||||
}
|
||||
|
||||
inline void PIXInsertTimingMarkerOnContextForEndEvent(_In_ ID3D12CommandQueue* commandQueue, UINT8 eventType)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(eventType);
|
||||
commandQueue->EndEvent();
|
||||
}
|
||||
|
||||
inline void PIXInsertGPUMarkerOnContextForBeginEvent(_In_ ID3D12GraphicsCommandList* commandList, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(eventType);
|
||||
commandList->BeginEvent(WINPIX_EVENT_PIX3BLOB_V2, data, size);
|
||||
}
|
||||
|
||||
inline void PIXInsertGPUMarkerOnContextForBeginEvent(_In_ ID3D12CommandQueue* commandQueue, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(eventType);
|
||||
commandQueue->BeginEvent(WINPIX_EVENT_PIX3BLOB_V2, data, size);
|
||||
}
|
||||
|
||||
inline void PIXInsertGPUMarkerOnContextForSetMarker(_In_ ID3D12GraphicsCommandList* commandList, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(eventType);
|
||||
commandList->SetMarker(WINPIX_EVENT_PIX3BLOB_V2, data, size);
|
||||
}
|
||||
|
||||
inline void PIXInsertGPUMarkerOnContextForSetMarker(_In_ ID3D12CommandQueue* commandQueue, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(eventType);
|
||||
commandQueue->SetMarker(WINPIX_EVENT_PIX3BLOB_V2, data, size);
|
||||
}
|
||||
|
||||
inline void PIXInsertGPUMarkerOnContextForEndEvent(_In_ ID3D12GraphicsCommandList* commandList, UINT8, void*, UINT)
|
||||
{
|
||||
commandList->EndEvent();
|
||||
}
|
||||
|
||||
inline void PIXInsertGPUMarkerOnContextForEndEvent(_In_ ID3D12CommandQueue* commandQueue, UINT8, void*, UINT)
|
||||
{
|
||||
commandQueue->EndEvent();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif //_PIX3_WIN_H_
|
||||
579
Kore/Backends/Graphics5/Direct3D12/pix/ThirdPartyNotices.txt
Normal file
579
Kore/Backends/Graphics5/Direct3D12/pix/ThirdPartyNotices.txt
Normal file
@ -0,0 +1,579 @@
|
||||
THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
|
||||
|
||||
Note: While Microsoft is not the author of the files below, Microsoft is
|
||||
offering you a license subject to the terms of the Microsoft Software License
|
||||
Terms for Microsoft PIX Developer Tool (the "Microsoft Program"). Microsoft
|
||||
reserves all other rights. The notices below are provided for informational
|
||||
purposes only and are not the license terms under which Microsoft distributes
|
||||
these files.
|
||||
|
||||
The Microsoft Program includes the following third-party software:
|
||||
|
||||
1. Boost v. 1.66.0 (https://sourceforge.net/projects/boost/files/boost/1.66.0)
|
||||
2. fmt v4.1.0 (https://github.com/fmtlib/fmt/releases/tag/4.1.0)
|
||||
3. SQLite 3 (http://www.sqlite.org/)
|
||||
4. AMD PIX Plugin
|
||||
5. nlohmann JSON (https://github.com/nlohmann/json)
|
||||
6. PresentMon (https://github.com/GameTechDev/PresentMon)
|
||||
7. DirectXTex (https://github.com/microsoft/directxtex)
|
||||
8. DirectXTK12 (https://github.com/microsoft/DirectXTK12)
|
||||
9. Guidelines Support Library (GSL) (https://github.com/microsoft/GSL)
|
||||
10. Windows Implementation Library (WIL) (https://github.com/microsoft/wil)
|
||||
11. GoogleTest (https://github.com/google/googletest/)
|
||||
12. Newtonsoft.Json (https://www.newtonsoft.com/json)
|
||||
13. WIX (https://wixtoolset.org/)
|
||||
14. Moq (https://github.com/moq/moq)
|
||||
15. FluentAssertions (https://github.com/fluentassertions/fluentassertions)
|
||||
16. .NET Community Toolkit (https://github.com/CommunityToolkit/dotnet)
|
||||
17. LiveCharts (https://lvcharts.com)
|
||||
18. NVIDIA PIX Plugin
|
||||
|
||||
As the recipient of the above third-party software, Microsoft sets forth a copy
|
||||
of the notices and other information below.
|
||||
|
||||
|
||||
BOOST NOTICES AND INFORMATION BEGIN HERE
|
||||
========================================
|
||||
|
||||
Boost v. 1.66.0
|
||||
Copyright Beman Dawes, David Abrahams, 1998-2005
|
||||
Copyright Rene Rivera 2006-2007
|
||||
Provided for Informational Purposes Only
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by this
|
||||
license (the "Software") to use, reproduce, display, distribute, execute, and
|
||||
transmit the Software, and to prepare derivative works of the Software, and to
|
||||
permit third-parties to whom the Software is furnished to do so, all subject to
|
||||
the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including the
|
||||
above license grant, this restriction and the following disclaimer, must be
|
||||
included in all copies of the Software, in whole or in part, and all derivative
|
||||
works of the Software, unless such copies or derivative works are solely in the
|
||||
form of machine-executable object code generated by a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE
|
||||
|
||||
END OF BOOST NOTICES AND INFORMATION
|
||||
====================================
|
||||
|
||||
FMT NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
|
||||
fmt v4.1.0
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
Provided for Informational Purposes Only
|
||||
BSD 2-clause
|
||||
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
END OF FMT NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
SQLITE3 NOTICES AND INFORMATION BEGIN HERE
|
||||
==========================================
|
||||
|
||||
https://www.sqlite.org/copyright.html
|
||||
SQLite Is Public Domain
|
||||
|
||||
All of the code and documentation in SQLite has been dedicated to the public
|
||||
domain by the authors. All code authors, and representatives of the companies
|
||||
they work for, have signed affidavits dedicating their contributions to the
|
||||
public domain and originals of those signed affidavits are stored in a firesafe
|
||||
at the main offices of Hwaci. Anyone is free to copy, modify, publish, use,
|
||||
compile, sell, or distribute the original SQLite code, either in source code
|
||||
form or as a compiled binary, for any purpose, commercial or non-commercial, and
|
||||
by any means.
|
||||
|
||||
The previous paragraph applies to the deliverable code and documentation in SQLite -
|
||||
those parts of the SQLite library that you actually bundle and ship with a larger
|
||||
application. Some scripts used as part of the build process (for example the "configure"
|
||||
scripts generated by autoconf) might fall under other open-source licenses. Nothing
|
||||
from these build scripts ever reaches the final deliverable SQLite library, however,
|
||||
and so the licenses associated with those scripts should not be a factor in assessing
|
||||
your rights to copy and use the SQLite library.
|
||||
|
||||
All of the deliverable code in SQLite has been written from scratch. No code has been
|
||||
taken from other projects or from the open internet. Every line of code can be traced
|
||||
back to its original author, and all of those authors have public domain dedications
|
||||
on file. So the SQLite code base is clean and is uncontaminated with licensed code
|
||||
from other projects.
|
||||
|
||||
END OF SQLITE3 NOTICES AND INFORMATION
|
||||
======================================
|
||||
|
||||
AMD NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
|
||||
AMD copyrighted code (MIT)
|
||||
Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
Microsoft copyrighted code (MIT)
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
This code is licensed under the MIT License (MIT).
|
||||
THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
|
||||
END OF AMD NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
NLOHMANN JSON NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013-2021 Niels Lohmann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
END OF NLOHMANN JSON NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
PRESENTMON NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
|
||||
Copyright (C) 2017-2021 Intel Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom
|
||||
the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
END OF PRESENTMON NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
DIRECTXTEX NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
|
||||
Copyright (c) 2011-2021 Microsoft Corp
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies
|
||||
or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
END OF DIRECTXTEX NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
DIRECTXTK12 NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
|
||||
Copyright (c) 2016-2021 Microsoft Corp
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify,
|
||||
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies
|
||||
or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
END OF DIRECTXTK12 NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
GSL NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
|
||||
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
|
||||
This code is licensed under the MIT License (MIT).
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
END OF GSL NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
WIL NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
|
||||
END OF WIL NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
GOOGLETEST NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
Copyright 2008, Google Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
END OF GOOGLETEST NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
NEWTONSOFT.JSON NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2007 James Newton-King
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
END OF NEWTONSOFT.JSON NOTICES AND INFORMATION
|
||||
=================================
|
||||
|
||||
WIX NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
Copyright (c) .NET Foundation and contributors. This software is released under
|
||||
the Microsoft Reciprocal License (MS-RL) (the "License"); you may not use the
|
||||
software except in compliance with the License.
|
||||
|
||||
The text of the Microsoft Reciprocal License (MS-RL) can be found online at:
|
||||
http://opensource.org/licenses/ms-rl
|
||||
|
||||
|
||||
Microsoft Reciprocal License (MS-RL)
|
||||
|
||||
This license governs use of the accompanying software. If you use the software,
|
||||
you accept this license. If you do not accept the license, do not use the
|
||||
software.
|
||||
|
||||
1. Definitions The terms "reproduce," "reproduction," "derivative works," and
|
||||
"distribution" have the same meaning here as under U.S. copyright law. A
|
||||
"contribution" is the original software, or any additions or changes to the
|
||||
software. A "contributor" is any person that distributes its contribution under
|
||||
this license. "Licensed patents" are a contributor's patent claims that read
|
||||
directly on its contribution.
|
||||
|
||||
2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license,
|
||||
including the license conditions and limitations in section 3, each contributor
|
||||
grants you a non-exclusive, worldwide, royalty-free copyright license to
|
||||
reproduce its contribution, prepare derivative works of its contribution, and
|
||||
distribute its contribution or any derivative works that you create. (B) Patent
|
||||
Grant- Subject to the terms of this license, including the license conditions and
|
||||
limitations in section 3, each contributor grants you a non-exclusive, worldwide,
|
||||
royalty-free license under its licensed patents to make, have made, use, sell,
|
||||
offer for sale, import, and/or otherwise dispose of its contribution in the
|
||||
software or derivative works of the contribution in the software.
|
||||
|
||||
3. Conditions and Limitations (A) Reciprocal Grants- For any file you distribute
|
||||
that contains code from the software (in source code or binary format), you must
|
||||
provide recipients the source code to that file along with a copy of this
|
||||
license, which license will govern that file. You may license other files that
|
||||
are entirely your own work and do not contain code from the software under any
|
||||
terms you choose. (B) No Trademark License- This license does not grant you
|
||||
rights to use any contributors' name, logo, or trademarks. (C) If you bring a
|
||||
patent claim against any contributor over patents that you claim are infringed by
|
||||
the software, your patent license from such contributor to the software ends
|
||||
automatically. (D) If you distribute any portion of the software, you must retain
|
||||
all copyright, patent, trademark, and attribution notices that are present in the
|
||||
software. (E) If you distribute any portion of the software in source code form,
|
||||
you may do so only under this license by including a complete copy of this
|
||||
license with your distribution. If you distribute any portion of the software in
|
||||
compiled or object code form, you may only do so under a license that complies
|
||||
with this license. (F) The software is licensed "as-is." You bear the risk of
|
||||
using it. The contributors give no express warranties, guarantees or conditions.
|
||||
You may have additional consumer rights under your local laws which this license
|
||||
cannot change. To the extent permitted under your local laws, the contributors
|
||||
exclude the implied warranties of merchantability, fitness for a particular
|
||||
purpose and non-infringement.
|
||||
|
||||
END OF WIX NOTICES AND INFORMATION
|
||||
=================================
|
||||
|
||||
|
||||
MOQ NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
MIT License
|
||||
|
||||
Copyright (c) Daniel Cazzulino and Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
END OF MOQ NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
|
||||
FLUENTASSERTIONS NOTICES AND INFORMATION BEGIN HERE
|
||||
===================================================
|
||||
Copyright [2010-2021] [Dennis Doomen]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
END OF FLUENTASSERTIONS NOTICES AND INFORMATION
|
||||
===============================================
|
||||
|
||||
.NET COMMUNITY TOOLKIT NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
MIT License
|
||||
|
||||
Copyright © .NET Foundation and Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
END OF .NET COMMUNITY TOOLKIT NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
LIVE CHARTS NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Alberto Rodriguez Orozco
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
END OF LIVE CHARTS NOTICES AND INFORMATION
|
||||
==================================
|
||||
|
||||
NVIDIA PIX PLUGIN NOTICES AND INFORMATION BEGIN HERE
|
||||
======================================
|
||||
Copyright (c) Microsoft Corporation.
|
||||
Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
END OF NVIDIA PIX PLUGIN NOTICES AND INFORMATION
|
||||
==================================
|
||||
Binary file not shown.
Binary file not shown.
21
Kore/Backends/Graphics5/Direct3D12/pix/license.txt
Normal file
21
Kore/Backends/Graphics5/Direct3D12/pix/license.txt
Normal file
@ -0,0 +1,21 @@
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Reference in New Issue
Block a user