/* * The program that drew the first-triangle frame on 2026-09-27, against that day's build plus * work not yet committed, with --out and no --warp. Shaders (vs_6_0 / ps_6_0, * compiled with dxc -Qstrip_reflect and embedded with xxd -i as shaders.h): * * struct V { float4 pos : SV_Position; float4 col : COLOR; }; * V vs_main(float2 pos : POSITION, float3 col : COLOR) * { * V o; * o.pos = float4(pos, 0.0, 1.0); * o.col = float4(col, 1.0); * return o; * } * float4 ps_main(V i) : SV_Target { return i.col; } */ /* First triangle: offscreen render target, one vertex-coloured triangle, read back to PAM. */ #include "sample_util.h" #include "shaders.h" #define WIDTH 640 #define HEIGHT 360 int main(int argc, char **argv) { static const float bg[4] = {0x16 / 255.0f, 0x16 / 255.0f, 0x1e / 255.0f, 1.0f}; static const float verts[] = { 0.0f, 0.75f, 0.576f, 0.2f, 0.918f, /* purple */ 0.55f, -0.7f, 0.176f, 0.831f, 0.749f, /* teal */ -0.55f, -0.7f, 0.957f, 0.247f, 0.369f, /* rose */ }; struct sample_args args; IDXGIFactory4 *factory; IDXGIAdapter1 *adapter; ID3D12Device *device; ID3D12CommandQueue *queue; ID3D12DescriptorHeap *rtv_heap; ID3D12Resource *target, *readback, *vb; ID3D12CommandAllocator *allocator; ID3D12GraphicsCommandList *list; ID3D12Fence *fence; ID3D12RootSignature *root; ID3D12PipelineState *pso; ID3DBlob *blob, *err = NULL; D3D12_COMMAND_QUEUE_DESC qd = {0}; D3D12_DESCRIPTOR_HEAP_DESC hd = {0}; D3D12_HEAP_PROPERTIES heap = {0}; D3D12_RESOURCE_DESC rd = {0}; D3D12_PLACED_SUBRESOURCE_FOOTPRINT fp; D3D12_CPU_DESCRIPTOR_HANDLE rtv; D3D12_ROOT_SIGNATURE_DESC rsd = {0}; D3D12_GRAPHICS_PIPELINE_STATE_DESC pd = {0}; D3D12_INPUT_ELEMENT_DESC il[] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; D3D12_VERTEX_BUFFER_VIEW vbv; D3D12_VIEWPORT vp = {0, 0, WIDTH, HEIGHT, 0, 1}; D3D12_RECT sc = {0, 0, WIDTH, HEIGHT}; D3D12_CLEAR_VALUE cv; D3D12_TEXTURE_COPY_LOCATION dst, src; UINT64 size, fence_value = 0; BYTE *data; void *map; parse_args(argc, argv, &args); CHECK(CreateDXGIFactory2(0, &IID_IDXGIFactory4, (void **)&factory)); adapter = get_adapter(factory, args.warp); CHECK(D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&device)); qd.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; CHECK(ID3D12Device_CreateCommandQueue(device, &qd, &IID_ID3D12CommandQueue, (void **)&queue)); hd.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; hd.NumDescriptors = 1; CHECK(ID3D12Device_CreateDescriptorHeap(device, &hd, &IID_ID3D12DescriptorHeap, (void **)&rtv_heap)); rtv = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(rtv_heap); heap.Type = D3D12_HEAP_TYPE_DEFAULT; rd.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; rd.Width = WIDTH; rd.Height = HEIGHT; rd.DepthOrArraySize = 1; rd.MipLevels = 1; rd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; rd.SampleDesc.Count = 1; rd.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; cv.Format = rd.Format; memcpy(cv.Color, bg, sizeof(bg)); CHECK(ID3D12Device_CreateCommittedResource(device, &heap, D3D12_HEAP_FLAG_NONE, &rd, D3D12_RESOURCE_STATE_RENDER_TARGET, &cv, &IID_ID3D12Resource, (void **)&target)); ID3D12Device_CreateRenderTargetView(device, target, NULL, rtv); ID3D12Device_GetCopyableFootprints(device, &rd, 0, 1, 0, &fp, NULL, NULL, &size); memset(&rd, 0, sizeof(rd)); rd.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; rd.Height = 1; rd.DepthOrArraySize = 1; rd.MipLevels = 1; rd.SampleDesc.Count = 1; rd.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; heap.Type = D3D12_HEAP_TYPE_READBACK; rd.Width = size; CHECK(ID3D12Device_CreateCommittedResource(device, &heap, D3D12_HEAP_FLAG_NONE, &rd, D3D12_RESOURCE_STATE_COPY_DEST, NULL, &IID_ID3D12Resource, (void **)&readback)); heap.Type = D3D12_HEAP_TYPE_UPLOAD; rd.Width = sizeof(verts); CHECK(ID3D12Device_CreateCommittedResource(device, &heap, D3D12_HEAP_FLAG_NONE, &rd, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &IID_ID3D12Resource, (void **)&vb)); CHECK(ID3D12Resource_Map(vb, 0, NULL, &map)); memcpy(map, verts, sizeof(verts)); ID3D12Resource_Unmap(vb, 0, NULL); vbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb); vbv.SizeInBytes = sizeof(verts); vbv.StrideInBytes = 5 * sizeof(float); rsd.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; CHECK(D3D12SerializeRootSignature(&rsd, D3D_ROOT_SIGNATURE_VERSION_1, &blob, &err)); CHECK(ID3D12Device_CreateRootSignature(device, 0, ID3D10Blob_GetBufferPointer(blob), ID3D10Blob_GetBufferSize(blob), &IID_ID3D12RootSignature, (void **)&root)); pd.pRootSignature = root; pd.VS.pShaderBytecode = vs_dxil; pd.VS.BytecodeLength = vs_dxil_len; pd.PS.pShaderBytecode = ps_dxil; pd.PS.BytecodeLength = ps_dxil_len; pd.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; pd.SampleMask = ~0u; pd.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; pd.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; pd.RasterizerState.DepthClipEnable = TRUE; pd.InputLayout.pInputElementDescs = il; pd.InputLayout.NumElements = 2; pd.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; pd.NumRenderTargets = 1; pd.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; pd.SampleDesc.Count = 1; CHECK(ID3D12Device_CreateGraphicsPipelineState(device, &pd, &IID_ID3D12PipelineState, (void **)&pso)); CHECK(ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT, &IID_ID3D12CommandAllocator, (void **)&allocator)); CHECK(ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator, pso, &IID_ID3D12GraphicsCommandList, (void **)&list)); CHECK(ID3D12Device_CreateFence(device, 0, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, (void **)&fence)); ID3D12GraphicsCommandList_ClearRenderTargetView(list, rtv, bg, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(list, 1, &rtv, FALSE, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(list, root); ID3D12GraphicsCommandList_RSSetViewports(list, 1, &vp); ID3D12GraphicsCommandList_RSSetScissorRects(list, 1, &sc); ID3D12GraphicsCommandList_IASetPrimitiveTopology(list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_IASetVertexBuffers(list, 0, 1, &vbv); ID3D12GraphicsCommandList_DrawInstanced(list, 3, 1, 0, 0); transition(list, target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); dst.pResource = readback; dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; dst.PlacedFootprint = fp; src.pResource = target; src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; src.SubresourceIndex = 0; ID3D12GraphicsCommandList_CopyTextureRegion(list, &dst, 0, 0, 0, &src, NULL); CHECK(ID3D12GraphicsCommandList_Close(list)); ID3D12CommandQueue_ExecuteCommandLists(queue, 1, (ID3D12CommandList **)&list); wait_for_fence(queue, fence, &fence_value); if (args.out) { CHECK(ID3D12Resource_Map(readback, 0, NULL, (void **)&data)); write_pam(args.out, data + fp.Offset, WIDTH, HEIGHT, fp.Footprint.RowPitch, 0); ID3D12Resource_Unmap(readback, 0, NULL); } printf("triangle: ok\n"); return 0; }