mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-11-07 22:06:33 +00:00
116 lines
6.0 KiB
C
116 lines
6.0 KiB
C
/* Direct3D 12 shader model 6 workload: runs a cs_6_0 compute shader (wave.hlsl, DXIL) that checks identities of the wave intrinsics and writes
|
|
* two words per thread into a UAV buffer: a mask of the identities that held, and the wave size. The buffer goes to C:\wave.raw. C:\wave.txt
|
|
* holds OK, SKIP when the device has no shader model 6 or wave operations, or the first failing step. */
|
|
#define COBJMACROS
|
|
#include <windows.h>
|
|
#include <d3d12.h>
|
|
#include "wave_shaders.h"
|
|
|
|
#define GROUPS 4
|
|
#define THREADS 64
|
|
#define WORDS (GROUPS * THREADS * 2)
|
|
|
|
static void write_file(const wchar_t *path, const void *data, DWORD size)
|
|
{
|
|
HANDLE f = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
|
DWORD n;
|
|
WriteFile(f, data, size, &n, NULL);
|
|
CloseHandle(f);
|
|
}
|
|
|
|
static void fail(const char *step, HRESULT hr)
|
|
{
|
|
char text[96];
|
|
int length = 0;
|
|
const char *prefix = "FAIL ";
|
|
while (*prefix)
|
|
text[length++] = *prefix++;
|
|
while (*step && length < 70)
|
|
text[length++] = *step++;
|
|
text[length++] = ' ';
|
|
for (int shift = 28; shift >= 0; shift -= 4)
|
|
text[length++] = "0123456789abcdef"[((unsigned)hr >> shift) & 15];
|
|
write_file(L"C:\\wave.txt", text, (DWORD)length);
|
|
ExitProcess(1);
|
|
}
|
|
|
|
#define CHECK(step, call) do { HRESULT result_ = (call); if (FAILED(result_)) fail(step, result_); } while (0)
|
|
|
|
static ID3D12Device *device;
|
|
|
|
static ID3D12Resource *make_buffer(D3D12_HEAP_TYPE heap_type, UINT64 size, D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES state, const char *step)
|
|
{
|
|
D3D12_HEAP_PROPERTIES heap = {heap_type, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 1, 1};
|
|
D3D12_RESOURCE_DESC desc = {D3D12_RESOURCE_DIMENSION_BUFFER, 0, size, 1, 1, 1, DXGI_FORMAT_UNKNOWN, {1, 0}, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags};
|
|
ID3D12Resource *buffer = NULL;
|
|
CHECK(step, ID3D12Device_CreateCommittedResource(device, &heap, D3D12_HEAP_FLAG_NONE, &desc, state, NULL, &IID_ID3D12Resource, (void **)&buffer));
|
|
return buffer;
|
|
}
|
|
|
|
void __stdcall entry(void)
|
|
{
|
|
CHECK("device", D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&device));
|
|
D3D12_FEATURE_DATA_SHADER_MODEL model = {D3D_SHADER_MODEL_6_0};
|
|
D3D12_FEATURE_DATA_D3D12_OPTIONS1 options1 = {0};
|
|
if (FAILED(ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_SHADER_MODEL, &model, sizeof model)) || model.HighestShaderModel < D3D_SHADER_MODEL_6_0 ||
|
|
FAILED(ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_D3D12_OPTIONS1, &options1, sizeof options1)) || !options1.WaveOps) {
|
|
write_file(L"C:\\wave.txt", "SKIP no wave operations", 23);
|
|
ExitProcess(0);
|
|
}
|
|
|
|
D3D12_COMMAND_QUEUE_DESC queue_desc = {D3D12_COMMAND_LIST_TYPE_DIRECT, 0, D3D12_COMMAND_QUEUE_FLAG_NONE, 0};
|
|
ID3D12CommandQueue *queue = NULL;
|
|
CHECK("queue", ID3D12Device_CreateCommandQueue(device, &queue_desc, &IID_ID3D12CommandQueue, (void **)&queue));
|
|
ID3D12CommandAllocator *allocator = NULL;
|
|
CHECK("allocator", ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT, &IID_ID3D12CommandAllocator, (void **)&allocator));
|
|
|
|
D3D12_ROOT_PARAMETER parameter = {D3D12_ROOT_PARAMETER_TYPE_UAV};
|
|
parameter.Descriptor.ShaderRegister = 0;
|
|
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
D3D12_ROOT_SIGNATURE_DESC root_desc = {1, ¶meter, 0, NULL, D3D12_ROOT_SIGNATURE_FLAG_NONE};
|
|
ID3DBlob *serialized = NULL, *errors = NULL;
|
|
CHECK("serialize root signature", D3D12SerializeRootSignature(&root_desc, D3D_ROOT_SIGNATURE_VERSION_1, &serialized, &errors));
|
|
ID3D12RootSignature *root = NULL;
|
|
CHECK("root signature", ID3D12Device_CreateRootSignature(device, 0, ID3D10Blob_GetBufferPointer(serialized), ID3D10Blob_GetBufferSize(serialized),
|
|
&IID_ID3D12RootSignature, (void **)&root));
|
|
D3D12_COMPUTE_PIPELINE_STATE_DESC pipeline_desc = {root, {wave_shader, sizeof wave_shader}};
|
|
ID3D12PipelineState *pipeline = NULL;
|
|
CHECK("compute pipeline", ID3D12Device_CreateComputePipelineState(device, &pipeline_desc, &IID_ID3D12PipelineState, (void **)&pipeline));
|
|
|
|
ID3D12Resource *results = make_buffer(D3D12_HEAP_TYPE_DEFAULT, WORDS * 4, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, "results");
|
|
ID3D12Resource *readback = make_buffer(D3D12_HEAP_TYPE_READBACK, WORDS * 4, D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST, "readback");
|
|
|
|
ID3D12GraphicsCommandList *list = NULL;
|
|
CHECK("list", ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator, pipeline, &IID_ID3D12GraphicsCommandList, (void **)&list));
|
|
ID3D12GraphicsCommandList_SetComputeRootSignature(list, root);
|
|
ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(list, 0, ID3D12Resource_GetGPUVirtualAddress(results));
|
|
ID3D12GraphicsCommandList_Dispatch(list, GROUPS, 1, 1);
|
|
D3D12_RESOURCE_BARRIER barrier = {D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, D3D12_RESOURCE_BARRIER_FLAG_NONE};
|
|
barrier.Transition.pResource = results;
|
|
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
|
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
|
ID3D12GraphicsCommandList_ResourceBarrier(list, 1, &barrier);
|
|
ID3D12GraphicsCommandList_CopyResource(list, readback, results);
|
|
CHECK("close", ID3D12GraphicsCommandList_Close(list));
|
|
|
|
ID3D12Fence *fence = NULL;
|
|
CHECK("fence", ID3D12Device_CreateFence(device, 0, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, (void **)&fence));
|
|
ID3D12CommandList *lists[] = {(ID3D12CommandList *)list};
|
|
ID3D12CommandQueue_ExecuteCommandLists(queue, 1, lists);
|
|
CHECK("signal", ID3D12CommandQueue_Signal(queue, fence, 1));
|
|
HANDLE event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
|
CHECK("completion", ID3D12Fence_SetEventOnCompletion(fence, 1, event));
|
|
if (WaitForSingleObject(event, 60000) != WAIT_OBJECT_0)
|
|
fail("wait", 0);
|
|
|
|
void *mapped = NULL;
|
|
D3D12_RANGE range = {0, WORDS * 4};
|
|
CHECK("map", ID3D12Resource_Map(readback, 0, &range, &mapped));
|
|
write_file(L"C:\\wave.raw", mapped, WORDS * 4);
|
|
D3D12_RANGE none = {0, 0};
|
|
ID3D12Resource_Unmap(readback, 0, &none);
|
|
write_file(L"C:\\wave.txt", "OK", 2);
|
|
ExitProcess(0);
|
|
}
|