/* * Copyright 2016-2017 Józef Kucia for CodeWeavers * Copyright 2020-2021 Philip Rebohle for Valve Corporation * Copyright 2020-2021 Joshua Ashton for Valve Corporation * Copyright 2020-2021 Hans-Kristian Arntzen for Valve Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API #include "d3d12_crosstest.h" void test_set_render_targets(void) { ID3D12DescriptorHeap *dsv_heap, *rtv_heap; ID3D12GraphicsCommandList *command_list; D3D12_CPU_DESCRIPTOR_HANDLE dsv, rtv; struct test_context context; ID3D12Device *device; HRESULT hr; if (!init_test_context(&context, NULL)) return; device = context.device; command_list = context.list; rtv_heap = create_cpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 4); dsv_heap = create_cpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 4); dsv = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(dsv_heap); rtv = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(rtv_heap); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &rtv, false, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &rtv, true, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &rtv, true, &dsv); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 0, &rtv, true, &dsv); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 0, &rtv, false, &dsv); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 0, NULL, true, &dsv); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 0, NULL, false, &dsv); hr = ID3D12GraphicsCommandList_Close(command_list); ok(hr == S_OK, "Failed to close command list, hr %#x.\n", hr); ID3D12DescriptorHeap_Release(rtv_heap); ID3D12DescriptorHeap_Release(dsv_heap); destroy_test_context(&context); } void test_draw_instanced(void) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; ID3D12GraphicsCommandList *command_list; struct test_context context; ID3D12CommandQueue *queue; if (!init_test_context(&context, NULL)) return; command_list = context.list; queue = context.queue; ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); if (!use_warp_device) { /* This draw call is ignored. */ ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); } ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); destroy_test_context(&context); } void test_draw_indexed_instanced(void) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const uint16_t indices[] = {0, 1, 2}; ID3D12GraphicsCommandList *command_list; struct test_context context; D3D12_INDEX_BUFFER_VIEW ibv; ID3D12CommandQueue *queue; ID3D12Resource *ib; if (!init_test_context(&context, NULL)) return; command_list = context.list; queue = context.queue; ib = create_upload_buffer(context.device, sizeof(indices), indices); ibv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(ib); ibv.SizeInBytes = sizeof(indices); ibv.Format = DXGI_FORMAT_R16_UINT; ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); if (!use_warp_device) { /* This draw call is ignored. */ ID3D12GraphicsCommandList_DrawIndexedInstanced(command_list, 3, 1, 0, 0, 0); } ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_IASetIndexBuffer(command_list, NULL); ID3D12GraphicsCommandList_IASetIndexBuffer(command_list, &ibv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawIndexedInstanced(command_list, 3, 1, 0, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); ID3D12Resource_Release(ib); destroy_test_context(&context); } void test_draw_no_descriptor_bindings(void) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; D3D12_ROOT_SIGNATURE_DESC root_signature_desc; D3D12_DESCRIPTOR_RANGE descriptor_range[2]; ID3D12GraphicsCommandList *command_list; D3D12_ROOT_PARAMETER root_parameters[2]; struct test_context_desc desc; struct test_context context; ID3D12CommandQueue *queue; HRESULT hr; memset(&desc, 0, sizeof(desc)); desc.no_root_signature = true; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; descriptor_range[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; descriptor_range[0].NumDescriptors = 2; descriptor_range[0].BaseShaderRegister = 0; descriptor_range[0].RegisterSpace = 0; descriptor_range[0].OffsetInDescriptorsFromTableStart = 1; root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; root_parameters[0].DescriptorTable.NumDescriptorRanges = 1; root_parameters[0].DescriptorTable.pDescriptorRanges = &descriptor_range[0]; root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; descriptor_range[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; descriptor_range[1].NumDescriptors = 1; descriptor_range[1].BaseShaderRegister = 0; descriptor_range[1].RegisterSpace = 0; descriptor_range[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; root_parameters[1].DescriptorTable.NumDescriptorRanges = 1; root_parameters[1].DescriptorTable.pDescriptorRanges = &descriptor_range[1]; root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; root_signature_desc.NumParameters = ARRAY_SIZE(root_parameters); root_signature_desc.pParameters = root_parameters; root_signature_desc.NumStaticSamplers = 0; root_signature_desc.pStaticSamplers = NULL; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; hr = create_root_signature(context.device, &root_signature_desc, &context.root_signature); ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr); context.pipeline_state = create_pipeline_state(context.device, context.root_signature, context.render_target_desc.Format, NULL, NULL, NULL); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); destroy_test_context(&context); } void test_multiple_render_targets(void) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; struct vec4 expected_vec4 = {0.0f, 0.0f, 0.0f, 1.0f}; D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc; ID3D12GraphicsCommandList *command_list; D3D12_CPU_DESCRIPTOR_HANDLE rtvs[3]; ID3D12Resource *render_targets[2]; struct test_context_desc desc; struct test_context context; ID3D12CommandQueue *queue; unsigned int i; HRESULT hr; static const DWORD ps_code[] = { #if 0 void main(out float4 target0 : SV_Target0, out float4 target1 : SV_Target1, out float4 target2 : SV_Target2) { target0 = float4(1.0f, 0.0f, 0.0f, 1.0f); target1 = float4(2.0f, 0.0f, 0.0f, 1.0f); target2 = float4(3.0f, 0.0f, 0.0f, 1.0f); } #endif 0x43425844, 0xc4325131, 0x8ba4a693, 0x08d15431, 0xcb990885, 0x00000001, 0x0000013c, 0x00000003, 0x0000002c, 0x0000003c, 0x000000a0, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000005c, 0x00000003, 0x00000008, 0x00000050, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x00000050, 0x00000001, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000050, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000094, 0x00000050, 0x00000025, 0x0100086a, 0x03000065, 0x001020f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000002, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x40000000, 0x00000000, 0x00000000, 0x3f800000, 0x08000036, 0x001020f2, 0x00000002, 0x00004002, 0x40400000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; memset(&desc, 0, sizeof(desc)); desc.rt_format = DXGI_FORMAT_R32G32B32A32_FLOAT; desc.rt_descriptor_count = ARRAY_SIZE(rtvs); desc.no_pipeline = true; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; init_pipeline_state_desc(&pso_desc, context.root_signature, 0, NULL, &ps, NULL); pso_desc.NumRenderTargets = ARRAY_SIZE(rtvs); for (i = 0; i < ARRAY_SIZE(rtvs); ++i) pso_desc.RTVFormats[i] = desc.rt_format; hr = ID3D12Device_CreateGraphicsPipelineState(context.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&context.pipeline_state); ok(hr == S_OK, "Failed to create state, hr %#x.\n", hr); rtvs[0] = get_cpu_rtv_handle(&context, context.rtv_heap, 2); rtvs[1] = get_cpu_rtv_handle(&context, context.rtv_heap, 0); rtvs[2] = get_cpu_rtv_handle(&context, context.rtv_heap, 1); create_render_target(&context, &desc, &render_targets[0], &rtvs[0]); create_render_target(&context, &desc, &render_targets[1], &rtvs[2]); for (i = 0; i < ARRAY_SIZE(rtvs); ++i) ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtvs[i], white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, ARRAY_SIZE(rtvs), rtvs, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); transition_resource_state(command_list, render_targets[0], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); transition_resource_state(command_list, render_targets[1], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); expected_vec4.x = 2.0f; check_sub_resource_vec4(context.render_target, 0, queue, command_list, &expected_vec4, 0); reset_command_list(command_list, context.allocator); expected_vec4.x = 1.0f; check_sub_resource_vec4(render_targets[0], 0, queue, command_list, &expected_vec4, 0); reset_command_list(command_list, context.allocator); expected_vec4.x = 3.0f; check_sub_resource_vec4(render_targets[1], 0, queue, command_list, &expected_vec4, 0); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); transition_resource_state(command_list, render_targets[0], D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); transition_resource_state(command_list, render_targets[1], D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, ARRAY_SIZE(rtvs), &context.rtv, true, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); transition_resource_state(command_list, render_targets[0], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); transition_resource_state(command_list, render_targets[1], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); expected_vec4.x = 1.0f; check_sub_resource_vec4(context.render_target, 0, queue, command_list, &expected_vec4, 0); reset_command_list(command_list, context.allocator); expected_vec4.x = 3.0f; check_sub_resource_vec4(render_targets[0], 0, queue, command_list, &expected_vec4, 0); reset_command_list(command_list, context.allocator); expected_vec4.x = 2.0f; check_sub_resource_vec4(render_targets[1], 0, queue, command_list, &expected_vec4, 0); reset_command_list(command_list, context.allocator); for (i = 0; i < ARRAY_SIZE(render_targets); ++i) ID3D12Resource_Release(render_targets[i]); destroy_test_context(&context); } void test_fractional_viewports(void) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; ID3D12GraphicsCommandList *command_list; D3D12_INPUT_LAYOUT_DESC input_layout; struct test_context_desc desc; D3D12_VERTEX_BUFFER_VIEW vbv; struct test_context context; struct resource_readback rb; ID3D12CommandQueue *queue; D3D12_VIEWPORT viewport; unsigned int i, x, y; ID3D12Resource *vb; static const DWORD vs_code[] = { #if 0 void main(in float4 in_position : POSITION, in float2 in_texcoord : TEXCOORD, out float4 position : SV_Position, out float2 texcoord : TEXCOORD) { position = in_position; texcoord = in_texcoord; } #endif 0x43425844, 0x4df282ca, 0x85c8bbfc, 0xd44ad19f, 0x1158be97, 0x00000001, 0x00000148, 0x00000003, 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044, 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000c03, 0x505f5653, 0x7469736f, 0x006e6f69, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x00102032, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x00102032, 0x00000001, 0x00101046, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE vs = {vs_code, sizeof(vs_code)}; static const DWORD ps_code[] = { #if 0 float4 main(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target { return float4(position.xy, texcoord); } #endif 0x43425844, 0xa15616bc, 0x6862ab1c, 0x28b915c0, 0xdb0df67c, 0x00000001, 0x0000011c, 0x00000003, 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000303, 0x505f5653, 0x7469736f, 0x006e6f69, 0x43584554, 0x44524f4f, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000005c, 0x00000040, 0x00000017, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03001062, 0x00101032, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x00102032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x001020c2, 0x00000000, 0x00101406, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; static const D3D12_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; static const struct { struct vec2 position; struct vec2 texcoord; } quad[] = { {{-1.0f, -1.0f}, {0.0f, 0.0f}}, {{-1.0f, 1.0f}, {0.0f, 1.0f}}, {{ 1.0f, -1.0f}, {1.0f, 0.0f}}, {{ 1.0f, 1.0f}, {1.0f, 1.0f}}, }; static const float viewport_offsets[] = { 0.0f, 1.0f / 2.0f, 1.0f / 4.0f, 1.0f / 8.0f, 1.0f / 16.0f, 1.0f / 32.0f, 1.0f / 64.0f, 1.0f / 128.0f, 1.0f / 256.0f, 63.0f / 128.0f, }; memset(&desc, 0, sizeof(desc)); desc.rt_format = DXGI_FORMAT_R32G32B32A32_FLOAT; desc.no_root_signature = true; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; context.root_signature = create_empty_root_signature(context.device, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); input_layout.pInputElementDescs = layout_desc; input_layout.NumElements = ARRAY_SIZE(layout_desc); context.pipeline_state = create_pipeline_state(context.device, context.root_signature, desc.rt_format, &vs, &ps, &input_layout); vb = create_upload_buffer(context.device, sizeof(quad), quad); vbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb); vbv.StrideInBytes = sizeof(*quad); vbv.SizeInBytes = sizeof(quad); for (i = 0; i < ARRAY_SIZE(viewport_offsets); ++i) { set_viewport(&viewport, viewport_offsets[i], viewport_offsets[i], context.render_target_desc.Width, context.render_target_desc.Height, 0.0f, 1.0f); if (i) transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, &vbv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 4, 1, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); get_texture_readback_with_command_list(context.render_target, 0, &rb, queue, command_list); for (y = 0; y < rb.height; ++y) { for (x = 0; x < rb.width; ++x) { const struct vec4 *v = get_readback_vec4(&rb, x, y); struct vec4 expected = {x + 0.5f, y + 0.5f, (x + 0.5f - viewport_offsets[i]) / context.render_target_desc.Width, 1.0f - (y + 0.5f - viewport_offsets[i]) / context.render_target_desc.Height}; ok(compare_float(v->x, expected.x, 0) && compare_float(v->y, expected.y, 0), "Got fragcoord {%.8e, %.8e}, expected {%.8e, %.8e} at (%u, %u), offset %.8e.\n", v->x, v->y, expected.x, expected.y, x, y, viewport_offsets[i]); ok(compare_float(v->z, expected.z, 2) && compare_float(v->w, expected.w, 2), "Got texcoord {%.8e, %.8e}, expected {%.8e, %.8e} at (%u, %u), offset %.8e.\n", v->z, v->w, expected.z, expected.w, x, y, viewport_offsets[i]); } } release_resource_readback(&rb); reset_command_list(command_list, context.allocator); } ID3D12Resource_Release(vb); destroy_test_context(&context); } void test_scissor(void) { ID3D12GraphicsCommandList *command_list; struct test_context_desc desc; struct test_context context; struct resource_readback rb; ID3D12CommandQueue *queue; unsigned int color; RECT scissor_rect; static const DWORD ps_code[] = { #if 0 float4 main(float4 position : SV_POSITION) : SV_Target { return float4(0.0, 1.0, 0.0, 1.0); } #endif 0x43425844, 0x30240e72, 0x012f250c, 0x8673c6ea, 0x392e4cec, 0x00000001, 0x000000d4, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03000065, 0x001020f2, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; static const float red[] = {1.0f, 0.0f, 0.0f, 1.0f}; memset(&desc, 0, sizeof(desc)); desc.rt_width = 640; desc.rt_height = 480; desc.ps = &ps; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; set_rect(&scissor_rect, 160, 120, 480, 360); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, red, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); get_texture_readback_with_command_list(context.render_target, 0, &rb, queue, command_list); color = get_readback_uint(&rb, 320, 60, 0); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_uint(&rb, 80, 240, 0); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_uint(&rb, 320, 240, 0); ok(compare_color(color, 0xff00ff00, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_uint(&rb, 560, 240, 0); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); color = get_readback_uint(&rb, 320, 420, 0); ok(compare_color(color, 0xff0000ff, 1), "Got unexpected color 0x%08x.\n", color); release_resource_readback(&rb); destroy_test_context(&context); } void test_draw_depth_no_ps(void) { D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc; ID3D12GraphicsCommandList *command_list; D3D12_INPUT_LAYOUT_DESC input_layout; struct depth_stencil_resource ds; struct test_context_desc desc; D3D12_VERTEX_BUFFER_VIEW vbv; struct test_context context; ID3D12CommandQueue *queue; ID3D12Resource *vb; HRESULT hr; static const D3D12_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; static const struct { struct vec4 position; } quad[] = { {{-1.0f, -1.0f, 0.5f, 1.0f}}, {{-1.0f, 1.0f, 0.5f, 1.0f}}, {{ 1.0f, -1.0f, 0.5f, 1.0f}}, {{ 1.0f, 1.0f, 0.5f, 1.0f}}, }; static const DWORD vs_code[] = { #if 0 void main(float4 in_position : POSITION, out float4 out_position : SV_POSITION) { out_position = in_position; } #endif 0x43425844, 0xa7a2f22d, 0x83ff2560, 0xe61638bd, 0x87e3ce90, 0x00000001, 0x000000d8, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000003c, 0x00010040, 0x0000000f, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; static const D3D12_SHADER_BYTECODE vs = {vs_code, sizeof(vs_code)}; memset(&desc, 0, sizeof(desc)); desc.no_render_target = true; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; vb = create_upload_buffer(context.device, sizeof(quad), quad); vbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb); vbv.StrideInBytes = sizeof(*quad); vbv.SizeInBytes = sizeof(quad); init_depth_stencil(&ds, context.device, 640, 480, 1, 1, DXGI_FORMAT_D32_FLOAT, 0, NULL); set_viewport(&context.viewport, 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1.0f); set_rect(&context.scissor_rect, 0, 0, 640, 480); context.root_signature = create_empty_root_signature(context.device, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); input_layout.pInputElementDescs = layout_desc; input_layout.NumElements = ARRAY_SIZE(layout_desc); init_pipeline_state_desc(&pso_desc, context.root_signature, 0, &vs, NULL, &input_layout); memset(&pso_desc.PS, 0, sizeof(pso_desc.PS)); pso_desc.NumRenderTargets = 0; pso_desc.DSVFormat = DXGI_FORMAT_D32_FLOAT; pso_desc.DepthStencilState.DepthEnable = true; pso_desc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; pso_desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; hr = ID3D12Device_CreateGraphicsPipelineState(context.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&context.pipeline_state); ok(hr == S_OK, "Failed to create graphics pipeline state, hr %#x.\n", hr); ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, ds.dsv_handle, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 0, NULL, false, &ds.dsv_handle); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, &vbv); ID3D12GraphicsCommandList_DrawInstanced(command_list, 4, 1, 0, 0); transition_resource_state(command_list, ds.texture, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_float(ds.texture, 0, queue, command_list, 0.5f, 1); destroy_depth_stencil(&ds); ID3D12Resource_Release(vb); destroy_test_context(&context); } void test_draw_depth_only(void) { D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc; ID3D12GraphicsCommandList *command_list; struct depth_stencil_resource ds; struct test_context_desc desc; struct resource_readback rb; struct test_context context; ID3D12CommandQueue *queue; unsigned int i, j; HRESULT hr; static const DWORD ps_code[] = { #if 0 float depth; float main() : SV_Depth { return depth; } #endif 0x43425844, 0x91af6cd0, 0x7e884502, 0xcede4f54, 0x6f2c9326, 0x00000001, 0x000000b0, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0xffffffff, 0x00000e01, 0x445f5653, 0x68747065, 0xababab00, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x02000065, 0x0000c001, 0x05000036, 0x0000c001, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; static const struct { float clear_depth; float depth; float expected_depth; } tests[] = { {0.0f, 0.0f, 0.0f}, {0.0f, 0.7f, 0.0f}, {0.0f, 0.8f, 0.0f}, {0.0f, 0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.7f, 0.7f}, {1.0f, 0.8f, 0.8f}, {1.0f, 0.5f, 0.5f}, }; memset(&desc, 0, sizeof(desc)); desc.no_render_target = true; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; init_depth_stencil(&ds, context.device, 640, 480, 1, 1, DXGI_FORMAT_D32_FLOAT, 0, NULL); set_viewport(&context.viewport, 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1.0f); set_rect(&context.scissor_rect, 0, 0, 640, 480); context.root_signature = create_32bit_constants_root_signature(context.device, 0, 1, D3D12_SHADER_VISIBILITY_PIXEL); init_pipeline_state_desc(&pso_desc, context.root_signature, 0, NULL, &ps, NULL); pso_desc.NumRenderTargets = 0; pso_desc.DSVFormat = DXGI_FORMAT_D32_FLOAT; pso_desc.DepthStencilState.DepthEnable = true; pso_desc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; pso_desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS; hr = ID3D12Device_CreateGraphicsPipelineState(context.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&context.pipeline_state); ok(SUCCEEDED(hr), "Failed to create graphics pipeline state, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(tests); ++i) { vkd3d_test_set_context("Test %u", i); ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, ds.dsv_handle, D3D12_CLEAR_FLAG_DEPTH, tests[i].clear_depth, 0, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 0, NULL, false, &ds.dsv_handle); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 0, 1, &tests[i].depth, 0); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, ds.texture, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_float(ds.texture, 0, queue, command_list, tests[i].expected_depth, 1); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, ds.texture, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE); } vkd3d_test_set_context(NULL); ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, ds.dsv_handle, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 0, NULL, false, &ds.dsv_handle); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { float depth = 1.0f / 16.0f * (j + 4 * i); ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 0, 1, &depth, 0); set_viewport(&context.viewport, 160.0f * j, 120.0f * i, 160.0f, 120.0f, 0.0f, 1.0f); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); } } transition_resource_state(command_list, ds.texture, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE); get_texture_readback_with_command_list(ds.texture, 0, &rb, queue, command_list); for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { float obtained_depth, expected_depth; obtained_depth = get_readback_float(&rb, 80 + j * 160, 60 + i * 120); expected_depth = 1.0f / 16.0f * (j + 4 * i); ok(compare_float(obtained_depth, expected_depth, 1), "Got unexpected depth %.8e at (%u, %u), expected %.8e.\n", obtained_depth, j, i, expected_depth); } } release_resource_readback(&rb); destroy_depth_stencil(&ds); destroy_test_context(&context); } void test_draw_uav_only(void) { ID3D12DescriptorHeap *cpu_descriptor_heap, *descriptor_heap; D3D12_ROOT_SIGNATURE_DESC root_signature_desc; D3D12_DESCRIPTOR_RANGE descriptor_range; ID3D12GraphicsCommandList *command_list; D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle; D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle; D3D12_ROOT_PARAMETER root_parameter; D3D12_RESOURCE_BARRIER barrier; struct test_context_desc desc; struct test_context context; ID3D12CommandQueue *queue; ID3D12Resource *resource; unsigned int i; HRESULT hr; static const DWORD ps_code[] = { #if 0 RWTexture2D u; void main() { InterlockedAdd(u[uint2(0, 0)], 1); } #endif 0x43425844, 0x237a8398, 0xe7b34c17, 0xa28c91a4, 0xb3614d73, 0x00000001, 0x0000009c, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000048, 0x00000050, 0x00000012, 0x0100086a, 0x0400189c, 0x0011e000, 0x00000000, 0x00003333, 0x0a0000ad, 0x0011e000, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004001, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; static const UINT zero[4] = {0}; memset(&desc, 0, sizeof(desc)); desc.no_render_target = true; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; descriptor_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; descriptor_range.NumDescriptors = 1; descriptor_range.BaseShaderRegister = 0; descriptor_range.RegisterSpace = 0; descriptor_range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; root_parameter.DescriptorTable.NumDescriptorRanges = 1; root_parameter.DescriptorTable.pDescriptorRanges = &descriptor_range; root_parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; root_signature_desc.NumParameters = 1; root_signature_desc.pParameters = &root_parameter; root_signature_desc.NumStaticSamplers = 0; root_signature_desc.pStaticSamplers = NULL; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; hr = create_root_signature(context.device, &root_signature_desc, &context.root_signature); ok(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); context.pipeline_state = create_pipeline_state(context.device, context.root_signature, 0, NULL, &ps, NULL); resource = create_default_texture(context.device, 1, 1, DXGI_FORMAT_R32_SINT, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); descriptor_heap = create_gpu_descriptor_heap(context.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1); cpu_descriptor_heap = create_cpu_descriptor_heap(context.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1); cpu_handle = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(descriptor_heap); gpu_handle = ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(descriptor_heap); ID3D12Device_CreateUnorderedAccessView(context.device, resource, NULL, NULL, cpu_handle); cpu_handle = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(cpu_descriptor_heap); ID3D12Device_CreateUnorderedAccessView(context.device, resource, NULL, NULL, cpu_handle); ID3D12GraphicsCommandList_ClearUnorderedAccessViewUint(command_list, gpu_handle, cpu_handle, resource, zero, 0, NULL); barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; barrier.UAV.pResource = resource; barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &barrier); set_rect(&context.scissor_rect, 0, 0, 1000, 1000); set_viewport(&context.viewport, 0.0f, 0.0f, 1.0f, 100.0f, 0.0f, 0.0f); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetDescriptorHeaps(command_list, 1, &descriptor_heap); ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, 0, gpu_handle); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); for (i = 0; i < 5; ++i) ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(resource, 0, queue, command_list, 500, 0); ID3D12DescriptorHeap_Release(cpu_descriptor_heap); ID3D12DescriptorHeap_Release(descriptor_heap); ID3D12Resource_Release(resource); destroy_test_context(&context); } void test_texture_resource_barriers(void) { ID3D12CommandAllocator *command_allocator; ID3D12GraphicsCommandList *command_list; D3D12_RESOURCE_BARRIER barriers[8]; ID3D12CommandQueue *queue; ID3D12Resource *resource; ID3D12Device *device; ULONG refcount; HRESULT hr; if (!(device = create_device())) { skip("Failed to create device.\n"); return; } queue = create_command_queue(device, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL); hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT, &IID_ID3D12CommandAllocator, (void **)&command_allocator); ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr); hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, command_allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list); ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr); resource = create_default_texture(device, 32, 32, DXGI_FORMAT_R8G8B8A8_UNORM, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COMMON); barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barriers[0].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barriers[0].Transition.pResource = resource; barriers[0].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_COMMON; barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &barriers[0]); barriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; barriers[1].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barriers[1].UAV.pResource = resource; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &barriers[1]); barriers[2].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barriers[2].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barriers[2].Transition.pResource = resource; barriers[2].Transition.Subresource = 0; barriers[2].Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; barriers[2].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &barriers[2]); barriers[3].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barriers[3].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barriers[3].Transition.pResource = resource; barriers[3].Transition.Subresource = 0; barriers[3].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; barriers[3].Transition.StateAfter = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &barriers[3]); barriers[4].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barriers[4].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barriers[4].Transition.pResource = resource; barriers[4].Transition.Subresource = 0; barriers[4].Transition.StateBefore = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; barriers[4].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &barriers[4]); barriers[5].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barriers[5].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barriers[5].Transition.pResource = resource; barriers[5].Transition.Subresource = 0; barriers[5].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE; barriers[5].Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &barriers[5]); barriers[6].Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; barriers[6].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barriers[6].UAV.pResource = resource; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &barriers[6]); ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &barriers[6]); barriers[7].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barriers[7].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barriers[7].Transition.pResource = resource; barriers[7].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; barriers[7].Transition.StateBefore = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; barriers[7].Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &barriers[7]); ID3D12GraphicsCommandList_ResourceBarrier(command_list, 8, barriers); hr = ID3D12GraphicsCommandList_Close(command_list); ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr); exec_command_list(queue, command_list); wait_queue_idle(device, queue); ID3D12GraphicsCommandList_Release(command_list); ID3D12CommandAllocator_Release(command_allocator); ID3D12Resource_Release(resource); ID3D12CommandQueue_Release(queue); refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount); } void test_bundle_state_inheritance(void) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; ID3D12GraphicsCommandList *command_list, *bundle; ID3D12CommandAllocator *bundle_allocator; struct test_context context; struct resource_readback rb; ID3D12CommandQueue *queue; ID3D12Device *device; unsigned int x, y; HRESULT hr; if (use_warp_device) { skip("Bundle state inheritance test crashes on WARP.\n"); return; } if (!init_test_context(&context, NULL)) return; device = context.device; command_list = context.list; queue = context.queue; hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_BUNDLE, &IID_ID3D12CommandAllocator, (void **)&bundle_allocator); ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr); hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_BUNDLE, bundle_allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&bundle); ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr); /* A bundle does not inherit the current pipeline state. */ ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(bundle, 3, 1, 0, 0); hr = ID3D12GraphicsCommandList_Close(bundle); ok(SUCCEEDED(hr), "Failed to close bundle, hr %#x.\n", hr); ID3D12GraphicsCommandList_ExecuteBundle(command_list, bundle); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); get_texture_readback_with_command_list(context.render_target, 0, &rb, queue, command_list); for (y = 0; y < rb.height; ++y) { for (x = 0; x < rb.width; ++x) { unsigned int v = get_readback_uint(&rb, x, y, 0); /* This works on AMD. */ ok(v == 0xffffffff || v == 0xff00ff00, "Got unexpected value 0x%08x at (%u, %u).\n", v, x, y); } } release_resource_readback(&rb); reset_command_list(command_list, context.allocator); reset_command_list(bundle, bundle_allocator); /* A bundle does not inherit the current primitive topology. */ transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_SetPipelineState(bundle, context.pipeline_state); ID3D12GraphicsCommandList_DrawInstanced(bundle, 3, 1, 0, 0); hr = ID3D12GraphicsCommandList_Close(bundle); ok(SUCCEEDED(hr), "Failed to close bundle, hr %#x.\n", hr); ID3D12GraphicsCommandList_ExecuteBundle(command_list, bundle); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); get_texture_readback_with_command_list(context.render_target, 0, &rb, queue, command_list); for (y = 0; y < rb.height; ++y) { for (x = 0; x < rb.width; ++x) { unsigned int v = get_readback_uint(&rb, x, y, 0); /* This works on AMD, even though the debug layer says that the primitive topology is undefined. */ ok(v == 0xffffffff || v == 0xff00ff00, "Got unexpected value 0x%08x at (%u, %u).\n", v, x, y); } } release_resource_readback(&rb); reset_command_list(command_list, context.allocator); reset_command_list(bundle, bundle_allocator); /* A bundle inherit all other states. */ transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_SetPipelineState(bundle, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(bundle, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_DrawInstanced(bundle, 3, 1, 0, 0); hr = ID3D12GraphicsCommandList_Close(bundle); ok(SUCCEEDED(hr), "Failed to close bundle, hr %#x.\n", hr); ID3D12GraphicsCommandList_ExecuteBundle(command_list, bundle); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); reset_command_list(command_list, context.allocator); reset_command_list(bundle, bundle_allocator); /* All state that is set in a bundle affects a command list. */ transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_SetGraphicsRootSignature(bundle, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(bundle, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(bundle, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); hr = ID3D12GraphicsCommandList_Close(bundle); ok(SUCCEEDED(hr), "Failed to close bundle, hr %#x.\n", hr); ID3D12GraphicsCommandList_ExecuteBundle(command_list, bundle); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); ID3D12GraphicsCommandList_Release(bundle); ID3D12CommandAllocator_Release(bundle_allocator); destroy_test_context(&context); } void test_null_vbv(void) { ID3D12GraphicsCommandList *command_list; D3D12_INPUT_LAYOUT_DESC input_layout; D3D12_VERTEX_BUFFER_VIEW vbv[2]; struct test_context_desc desc; struct test_context context; ID3D12CommandQueue *queue; ID3D12Resource *vb; static const D3D12_INPUT_ELEMENT_DESC layout_desc[] = { {"SV_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; static const DWORD vs_code[] = { #if 0 struct vs_data { float4 pos : SV_POSITION; float4 color : COLOR; }; void main(in struct vs_data vs_input, out struct vs_data vs_output) { vs_output.pos = vs_input.pos; vs_output.color = vs_input.color; } #endif 0x43425844, 0xd5b32785, 0x35332906, 0x4d05e031, 0xf66a58af, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE vs = {vs_code, sizeof(vs_code)}; static const DWORD ps_code[] = { #if 0 struct ps_data { float4 pos : SV_POSITION; float4 color : COLOR; }; float4 main(struct ps_data ps_input) : SV_Target { return ps_input.color; } #endif 0x43425844, 0x89803e59, 0x3f798934, 0xf99181df, 0xf5556512, 0x00000001, 0x000000f4, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; static const struct vec4 positions[] = { {-1.0f, -1.0f, 0.0f, 1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f}, { 1.0f, -1.0f, 0.0f, 1.0f}, { 1.0f, 1.0f, 0.0f, 1.0f}, }; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; memset(&desc, 0, sizeof(desc)); desc.no_root_signature = true; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; context.root_signature = create_empty_root_signature(context.device, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); input_layout.pInputElementDescs = layout_desc; input_layout.NumElements = ARRAY_SIZE(layout_desc); context.pipeline_state = create_pipeline_state(context.device, context.root_signature, context.render_target_desc.Format, &vs, &ps, &input_layout); vb = create_upload_buffer(context.device, sizeof(positions), positions); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); vbv[0].BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb); vbv[0].StrideInBytes = sizeof(*positions); vbv[0].SizeInBytes = sizeof(positions); vbv[1] = vbv[0]; ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, ARRAY_SIZE(vbv), vbv); vbv[1].BufferLocation = 0; vbv[1].StrideInBytes = 0; vbv[1].SizeInBytes = 0; ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, ARRAY_SIZE(vbv), vbv); /* Call should be ignored. */ ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, NULL); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 1, 1, NULL); ID3D12GraphicsCommandList_DrawInstanced(command_list, 4, 4, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0x00000000, 0); ID3D12Resource_Release(vb); destroy_test_context(&context); } void test_vbv_stride_edge_cases(void) { D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc; D3D12_STREAM_OUTPUT_BUFFER_VIEW so_view; D3D12_INPUT_LAYOUT_DESC input_layout; D3D12_SO_DECLARATION_ENTRY so_entry; struct test_context_desc desc; D3D12_VERTEX_BUFFER_VIEW vbv; struct resource_readback rb; struct test_context context; ID3D12Resource *vb, *xfb; ID3D12PipelineState *pso; unsigned int i; static const D3D12_INPUT_ELEMENT_DESC layout_desc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; static const DWORD vs_code[] = { #if 0 float4 main(float4 pos : POSITION) : SV_Position { return pos; } #endif 0x43425844, 0x1808c035, 0xc030df61, 0x84df42ec, 0xfc8e362e, 0x00000001, 0x000000dc, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x58454853, 0x00000040, 0x00010050, 0x00000010, 0x0100086a, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; static const D3D12_SHADER_BYTECODE vs = { vs_code, sizeof(vs_code) }; const UINT so_stride = 16; float vb_data[1024]; /* Various edge case behavior when stride < offset. * This is actually broken on native AMD drivers where bounds checking * happens based on vertex index being less than VBV size / stride. */ struct test_case { UINT stride; UINT size; float reference[8]; }; /* Negative value marks case which should be 0.0f due to robustness. * The positive value denotes the value we should read if robustness does not work as expected. */ static const struct test_case tests[] = { /* Stride 0 should always work as expected on AMD. */ { 0, 4, { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }, { 0, 8, { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }, { 0, 12, { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }, { 0, 16, { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }, /* Fully OOB */ { 0, 32, { 4.0f, 5.0f, 6.0f, 7.0f, 4.0f, 5.0f, 6.0f, 7.0f } }, /* Fine */ { 4, 16, { -4.0f, -5.0f, -6.0f, -7.0f, -5.0f, -6.0f, -7.0f, -8.0f } }, /* Fully OOB, but native D3D12 AMD driver thinks there are valid elements here. */ { 4, 36, { 4.0f, 5.0f, 6.0f, 7.0f, 5.0f, 6.0f, 7.0f, 8.0f } }, /* Fine. There should be room for 2 vertices here. */ { 8, 16, { -4.0f, -5.0f, -6.0f, -7.0f, -6.0f, -7.0f, -8.0f, -9.0f } }, /* Fully OOB, but native D3D12 AMD driver thinks there are valid elements here. */ { 8, 40, { 4.0f, 5.0f, 6.0f, 7.0f, 6.0f, 7.0f, 8.0f, 9.0f } }, /* Fine. There should be room for 2. */ { 12, 16, { -4.0f, -5.0f, -6.0f, -7.0f, 0.0f, 0.0f, 0.0f, 0.0f } }, /* Fully OOB, but native D3D12 AMD driver thinks there is one valid element. */ { 12, 44, { 4.0f, 5.0f, 6.0f, 7.0f, 7.0f, 8.0f, 9.0f, 10.0f } }, /* Fine. There should be room for 2. */ }; memset(&desc, 0, sizeof(desc)); desc.no_root_signature = true; if (!init_test_context(&context, &desc)) return; context.root_signature = create_empty_root_signature(context.device, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT); input_layout.pInputElementDescs = layout_desc; input_layout.NumElements = ARRAY_SIZE(layout_desc); init_pipeline_state_desc(&pso_desc, context.root_signature, DXGI_FORMAT_UNKNOWN, &vs, NULL, &input_layout); pso_desc.PS.BytecodeLength = 0; pso_desc.PS.pShaderBytecode = NULL; pso_desc.StreamOutput.NumEntries = 1; pso_desc.StreamOutput.RasterizedStream = 0; pso_desc.StreamOutput.pBufferStrides = &so_stride; pso_desc.StreamOutput.NumStrides = 1; pso_desc.StreamOutput.pSODeclaration = &so_entry; pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; so_entry.ComponentCount = 4; so_entry.OutputSlot = 0; so_entry.SemanticIndex = 0; so_entry.SemanticName = "SV_Position"; so_entry.StartComponent = 0; so_entry.Stream = 0; xfb = create_default_buffer(context.device, 4096, D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_STREAM_OUT); for (i = 0; i < ARRAY_SIZE(vb_data); i++) vb_data[i] = (float)i; vb = create_upload_buffer(context.device, sizeof(vb_data), vb_data); ID3D12Device_CreateGraphicsPipelineState(context.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pso); ID3D12GraphicsCommandList_SetGraphicsRootSignature(context.list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(context.list, pso); so_view.BufferFilledSizeLocation = ID3D12Resource_GetGPUVirtualAddress(xfb); so_view.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(xfb) + 16; so_view.SizeInBytes = 4096 - 16; ID3D12GraphicsCommandList_SOSetTargets(context.list, 0, 1, &so_view); ID3D12GraphicsCommandList_IASetPrimitiveTopology(context.list, D3D_PRIMITIVE_TOPOLOGY_POINTLIST); vbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb); for (i = 0; i < ARRAY_SIZE(tests); i++) { const D3D12_VIEWPORT vp = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f }; const D3D12_RECT rect = { 0, 0, 1, 1 }; vbv.SizeInBytes = tests[i].size; vbv.StrideInBytes = tests[i].stride; ID3D12GraphicsCommandList_RSSetViewports(context.list, 1, &vp); ID3D12GraphicsCommandList_RSSetScissorRects(context.list, 1, &rect); ID3D12GraphicsCommandList_IASetVertexBuffers(context.list, 0, 1, &vbv); ID3D12GraphicsCommandList_DrawInstanced(context.list, 2, 1, 0, 0); } transition_resource_state(context.list, xfb, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_RESOURCE_STATE_COPY_SOURCE); get_buffer_readback_with_command_list(xfb, DXGI_FORMAT_R32G32B32A32_FLOAT, &rb, context.queue, context.list); for (i = 0; i < ARRAY_SIZE(tests); i++) { const struct vec4 *v0, *v1; v0 = get_readback_vec4(&rb, 1 + 2 * i, 0); v1 = get_readback_vec4(&rb, 2 + 2 * i, 0); #define check(dat, ref_index) do { \ float ref = tests[i].reference[ref_index]; \ bool robust_is_zero = ref < 0.0f; \ ref = fabsf(ref); \ if (robust_is_zero && dat == ref) \ skip("Test %u, index %u expected 0 output, but robustness failed. Got expected output as if robustness did not happen.\n", i, ref_index); \ else \ ok(dat == ref || (robust_is_zero && dat == 0.0f), "Test %u, index %u, %f != %f\n", i, ref_index, dat, ref); \ } while(0) check(v0->x, 0); check(v0->y, 1); check(v0->z, 2); check(v0->w, 3); check(v1->x, 4); check(v1->y, 5); check(v1->z, 6); check(v1->w, 7); #undef check } release_resource_readback(&rb); ID3D12PipelineState_Release(pso); ID3D12Resource_Release(xfb); ID3D12Resource_Release(vb); destroy_test_context(&context); } void test_execute_indirect(void) { ID3D12Resource *argument_buffer, *count_buffer, *uav; D3D12_ROOT_SIGNATURE_DESC root_signature_desc; ID3D12CommandSignature *command_signature; ID3D12GraphicsCommandList *command_list; D3D12_INPUT_LAYOUT_DESC input_layout; D3D12_ROOT_PARAMETER root_parameter; ID3D12PipelineState *pipeline_state; ID3D12RootSignature *root_signature; struct test_context_desc desc; D3D12_VERTEX_BUFFER_VIEW vbv; D3D12_INDEX_BUFFER_VIEW ibv; struct resource_readback rb; struct test_context context; ID3D12CommandQueue *queue; ID3D12Resource *vb, *ib; unsigned int i; D3D12_BOX box; HRESULT hr; static const struct { struct vec4 position; uint32_t color; } vertices[] = { {{-1.0f, -1.0f, 0.0f, 1.0f}, 0xffffff00}, {{-1.0f, 1.0f, 0.0f, 1.0f}, 0xffffff00}, {{ 1.0f, -1.0f, 0.0f, 1.0f}, 0xffffff00}, {{ 1.0f, 1.0f, 0.0f, 1.0f}, 0xffffff00}, {{-1.0f, -1.0f, 0.0f, 1.0f}, 0xff00ff00}, {{-1.0f, 0.5f, 0.0f, 1.0f}, 0xff00ff00}, {{ 0.5f, -1.0f, 0.0f, 1.0f}, 0xff00ff00}, {{ 0.5f, 0.5f, 0.0f, 1.0f}, 0xff00ff00}, {{-1.0f, -1.0f, 0.0f, 1.0f}, 0xff00ff00}, {{-1.0f, 1.0f, 0.0f, 1.0f}, 0xff00ff00}, {{ 1.0f, -1.0f, 0.0f, 1.0f}, 0xff00ff00}, {{ 1.0f, 1.0f, 0.0f, 1.0f}, 0xff00ff00}, }; static const uint32_t indices[] = {0, 1, 2, 3, 2, 1}; static const D3D12_INPUT_ELEMENT_DESC layout_desc[] = { {"SV_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; static const DWORD vs_code[] = { #if 0 struct vs_data { float4 pos : SV_POSITION; float4 color : COLOR; }; void main(in struct vs_data vs_input, out struct vs_data vs_output) { vs_output.pos = vs_input.pos; vs_output.color = vs_input.color; } #endif 0x43425844, 0xd5b32785, 0x35332906, 0x4d05e031, 0xf66a58af, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE vs = {vs_code, sizeof(vs_code)}; static const DWORD ps_code[] = { #if 0 struct ps_data { float4 pos : SV_POSITION; float4 color : COLOR; }; float4 main(struct ps_data ps_input) : SV_Target { return ps_input.color; } #endif 0x43425844, 0x89803e59, 0x3f798934, 0xf99181df, 0xf5556512, 0x00000001, 0x000000f4, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; static const DWORD cs_code[] = { #if 0 RWByteAddressBuffer o; [numthreads(1, 1, 1)] void main(uint3 group_id : SV_groupID) { uint idx = group_id.x + group_id.y * 2 + group_id.z * 6; o.Store(idx * 4, idx); } #endif 0x43425844, 0xfdd6a339, 0xf3b8096e, 0xb5977014, 0xcdb26cfd, 0x00000001, 0x00000118, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000c4, 0x00050050, 0x00000031, 0x0100086a, 0x0300009d, 0x0011e000, 0x00000000, 0x0200005f, 0x00021072, 0x02000068, 0x00000001, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x06000029, 0x00100012, 0x00000000, 0x0002101a, 0x00004001, 0x00000001, 0x0600001e, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0002100a, 0x08000023, 0x00100012, 0x00000000, 0x0002102a, 0x00004001, 0x00000006, 0x0010000a, 0x00000000, 0x07000029, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000002, 0x070000a6, 0x0011e012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0100003e, }; static const struct argument_data { D3D12_DRAW_ARGUMENTS draws[4]; D3D12_DISPATCH_ARGUMENTS dispatch; D3D12_DRAW_INDEXED_ARGUMENTS indexed_draws[2]; } argument_data = { {{6, 1, 4, 0}, {6, 1, 8, 0}, {6, 1, 0, 0}}, {2, 3, 4}, {{6, 1, 0, 0, 0}, {6, 1, 0, 4, 0}}, }; static const uint32_t count_data[] = {2, 1}; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; memset(&desc, 0, sizeof(desc)); desc.root_signature_flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; desc.no_pipeline = true; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; input_layout.pInputElementDescs = layout_desc; input_layout.NumElements = ARRAY_SIZE(layout_desc); context.pipeline_state = create_pipeline_state(context.device, context.root_signature, context.render_target_desc.Format, &vs, &ps, &input_layout); vb = create_upload_buffer(context.device, sizeof(vertices), vertices); vbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb); vbv.StrideInBytes = sizeof(*vertices); vbv.SizeInBytes = sizeof(vertices); ib = create_upload_buffer(context.device, sizeof(indices), indices); ibv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(ib); ibv.SizeInBytes = sizeof(indices); ibv.Format = DXGI_FORMAT_R32_UINT; argument_buffer = create_upload_buffer(context.device, sizeof(argument_data), &argument_data); count_buffer = create_upload_buffer(context.device, sizeof(count_data), count_data); command_signature = create_command_signature(context.device, D3D12_INDIRECT_ARGUMENT_TYPE_DRAW); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, &vbv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_ExecuteIndirect(command_list, command_signature, 2, argument_buffer, 0, NULL, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, &vbv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_ExecuteIndirect(command_list, command_signature, 4, argument_buffer, 0, count_buffer, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); reset_command_list(command_list, context.allocator); ID3D12CommandSignature_Release(command_signature); command_signature = create_command_signature(context.device, D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH); uav = create_default_buffer(context.device, 2 * 3 * 4 * sizeof(UINT), D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; root_parameter.Descriptor.ShaderRegister = 0; root_parameter.Descriptor.RegisterSpace = 0; root_parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; root_signature_desc.NumParameters = 1; root_signature_desc.pParameters = &root_parameter; root_signature_desc.NumStaticSamplers = 0; root_signature_desc.pStaticSamplers = NULL; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; hr = create_root_signature(context.device, &root_signature_desc, &root_signature); ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr); ID3D12GraphicsCommandList_SetComputeRootSignature(command_list, root_signature); pipeline_state = create_compute_pipeline_state(context.device, root_signature, shader_bytecode(cs_code, sizeof(cs_code))); ID3D12GraphicsCommandList_SetPipelineState(command_list, pipeline_state); ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(command_list, 0, ID3D12Resource_GetGPUVirtualAddress(uav)); ID3D12GraphicsCommandList_ExecuteIndirect(command_list, command_signature, 1, argument_buffer, offsetof(struct argument_data, dispatch), NULL, 0); transition_sub_resource_state(command_list, uav, 0, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE); get_buffer_readback_with_command_list(uav, DXGI_FORMAT_R32_UINT, &rb, queue, command_list); for (i = 0; i < rb.width; ++i) { unsigned int ret = get_readback_uint(&rb, i, 0, 0); ok(ret == i, "Got unexpected result %#x at index %u.\n", ret, i); } release_resource_readback(&rb); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); ID3D12CommandSignature_Release(command_signature); command_signature = create_command_signature(context.device, D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_IASetIndexBuffer(command_list, &ibv); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, &vbv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_ExecuteIndirect(command_list, command_signature, ARRAY_SIZE(argument_data.indexed_draws), argument_buffer, offsetof(struct argument_data, indexed_draws), NULL, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); get_texture_readback_with_command_list(context.render_target, 0, &rb, queue, command_list); set_box(&box, 0, 0, 0, 32, 8, 1); check_readback_data_uint(&rb, &box, 0xffffff00, 0); set_box(&box, 24, 8, 0, 32, 32, 1); check_readback_data_uint(&rb, &box, 0xffffff00, 0); set_box(&box, 0, 8, 0, 24, 32, 1); check_readback_data_uint(&rb, &box, 0xff00ff00, 0); release_resource_readback(&rb); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_IASetIndexBuffer(command_list, &ibv); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, &vbv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_ExecuteIndirect(command_list, command_signature, ARRAY_SIZE(argument_data.indexed_draws), argument_buffer, offsetof(struct argument_data, indexed_draws), count_buffer, sizeof(uint32_t)); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xffffff00, 0); ID3D12PipelineState_Release(pipeline_state); ID3D12RootSignature_Release(root_signature); ID3D12Resource_Release(ib); ID3D12Resource_Release(uav); ID3D12Resource_Release(vb); ID3D12CommandSignature_Release(command_signature); ID3D12Resource_Release(argument_buffer); ID3D12Resource_Release(count_buffer); destroy_test_context(&context); } void test_dispatch_zero_thread_groups(void) { D3D12_ROOT_SIGNATURE_DESC root_signature_desc; ID3D12CommandSignature *command_signature; ID3D12GraphicsCommandList *command_list; D3D12_ROOT_PARAMETER root_parameters[2]; ID3D12Resource *argument_buffer, *uav; struct resource_readback rb; struct test_context context; ID3D12CommandQueue *queue; unsigned int ret, i; HRESULT hr; static const DWORD cs_code[] = { #if 0 RWByteAddressBuffer o; uint v; [numthreads(1, 1, 1)] void main() { o.Store(0, v); } #endif 0x43425844, 0x3ad946e3, 0x83e33b81, 0x83532aa4, 0x40831f89, 0x00000001, 0x000000b0, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x0000005c, 0x00050050, 0x00000017, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300009d, 0x0011e000, 0x00000000, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x080000a6, 0x0011e012, 0x00000000, 0x00004001, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x0100003e, }; static const D3D12_DISPATCH_ARGUMENTS argument_data[] = { {1, 1, 1}, {0, 3, 4}, {0, 0, 4}, {0, 0, 0}, {4, 0, 0}, {4, 0, 3}, {4, 2, 0}, {0, 2, 0}, {0, 0, 0}, }; if (!init_compute_test_context(&context)) return; command_list = context.list; queue = context.queue; argument_buffer = create_upload_buffer(context.device, sizeof(argument_data), &argument_data); command_signature = create_command_signature(context.device, D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH); uav = create_default_buffer(context.device, 2 * 256, /* minTexelBufferOffsetAlignment */ D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; root_parameters[0].Descriptor.ShaderRegister = 0; root_parameters[0].Descriptor.RegisterSpace = 0; root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; root_parameters[1].Constants.ShaderRegister = 0; root_parameters[1].Constants.RegisterSpace = 0; root_parameters[1].Constants.Num32BitValues = 1; root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; root_signature_desc.NumParameters = 2; root_signature_desc.pParameters = root_parameters; root_signature_desc.NumStaticSamplers = 0; root_signature_desc.pStaticSamplers = NULL; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; hr = create_root_signature(context.device, &root_signature_desc, &context.root_signature); ok(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); context.pipeline_state = create_compute_pipeline_state(context.device, context.root_signature, shader_bytecode(cs_code, sizeof(cs_code))); ID3D12GraphicsCommandList_SetComputeRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(command_list, 0, ID3D12Resource_GetGPUVirtualAddress(uav)); for (i = 0; i < ARRAY_SIZE(argument_data); ++i) { ID3D12GraphicsCommandList_SetComputeRoot32BitConstant(command_list, 1, 10 + i, 0); ID3D12GraphicsCommandList_ExecuteIndirect(command_list, command_signature, 1, argument_buffer, i * sizeof(*argument_data), NULL, 0); } ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(command_list, 0, ID3D12Resource_GetGPUVirtualAddress(uav) + 256); for (i = 0; i < ARRAY_SIZE(argument_data); ++i) { const D3D12_DISPATCH_ARGUMENTS *arg = &argument_data[i]; ID3D12GraphicsCommandList_SetComputeRoot32BitConstant(command_list, 1, 50 + i, 0); ID3D12GraphicsCommandList_Dispatch(command_list, arg->ThreadGroupCountX, arg->ThreadGroupCountY, arg->ThreadGroupCountZ); } transition_sub_resource_state(command_list, uav, 0, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE); get_buffer_readback_with_command_list(uav, DXGI_FORMAT_R32_UINT, &rb, queue, command_list); ret = get_readback_uint(&rb, 0, 0, 0); ok(ret == 10, "Got unexpected result %#x.\n", ret); ret = get_readback_uint(&rb, 64, 0, 0); ok(ret == 50, "Got unexpected result %#x.\n", ret); release_resource_readback(&rb); ID3D12Resource_Release(uav); ID3D12CommandSignature_Release(command_signature); ID3D12Resource_Release(argument_buffer); destroy_test_context(&context); } void test_unaligned_vertex_stride(void) { ID3D12PipelineState *instance_pipeline_state; ID3D12GraphicsCommandList *command_list; D3D12_INPUT_LAYOUT_DESC input_layout; D3D12_VERTEX_BUFFER_VIEW vbv[2]; struct test_context_desc desc; struct test_context context; ID3D12CommandQueue *queue; ID3D12Resource *vb[2]; unsigned int i; static const D3D12_INPUT_ELEMENT_DESC layout_desc[] = { {"sv_position", 0, DXGI_FORMAT_R16G16B16A16_SNORM, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"color", 0, DXGI_FORMAT_R16G16B16A16_SNORM, 1, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; static const D3D12_INPUT_ELEMENT_DESC instance_layout_desc[] = { {"sv_position", 0, DXGI_FORMAT_R16G16B16A16_SNORM, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"color", 0, DXGI_FORMAT_R16G16B16A16_SNORM, 1, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 0}, }; static const DWORD vs_code[] = { #if 0 struct vs_data { float4 pos : SV_POSITION; float4 color : COLOR; }; void main(in struct vs_data vs_input, out struct vs_data vs_output) { vs_output.pos = vs_input.pos; vs_output.color = vs_input.color; } #endif 0x43425844, 0xd5b32785, 0x35332906, 0x4d05e031, 0xf66a58af, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE vs = { vs_code, sizeof(vs_code) }; static const DWORD ps_code[] = { #if 0 struct ps_data { float4 pos : SV_POSITION; float4 color : COLOR; }; float4 main(struct ps_data ps_input) : SV_Target { return ps_input.color; } #endif 0x43425844, 0x89803e59, 0x3f798934, 0xf99181df, 0xf5556512, 0x00000001, 0x000000f4, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = { ps_code, sizeof(ps_code) }; struct i16vec4 { int16_t x, y, z, w; }; struct unaligned_i16vec4 { uint8_t blob[2 * 4 + 1]; }; #define I16_MIN -0x7fff #define I16_MAX 0x7fff static const struct i16vec4 positions[] = { {I16_MIN, I16_MIN, 0.0f, I16_MAX}, {I16_MIN, I16_MAX, 0.0f, I16_MAX}, {I16_MAX, I16_MIN, 0.0f, I16_MAX}, {I16_MAX, I16_MAX, 0.0f, I16_MAX}, }; static const struct i16vec4 colors[] = { {I16_MAX, 0, 0, 0}, {0, I16_MAX, 0, 0}, {0, 0, I16_MAX, 0}, {0, 0, 0, I16_MAX}, {0, 0, 0, I16_MAX}, {0, 0, I16_MAX, 0}, {0, I16_MAX, 0, 0}, {I16_MAX, 0, 0, 0}, }; static const float white[] = { 1.0f, 1.0f, 1.0f, 1.0f }; struct unaligned_i16vec4 unaligned_colors[ARRAY_SIZE(colors)]; for (i = 0; i < ARRAY_SIZE(colors); i++) memcpy(&unaligned_colors[i], &colors[i], sizeof(*colors)); memset(&desc, 0, sizeof(desc)); desc.no_root_signature = true; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; context.root_signature = create_empty_root_signature(context.device, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); input_layout.pInputElementDescs = layout_desc; input_layout.NumElements = ARRAY_SIZE(layout_desc); context.pipeline_state = create_pipeline_state(context.device, context.root_signature, context.render_target_desc.Format, &vs, &ps, &input_layout); input_layout.pInputElementDescs = instance_layout_desc; input_layout.NumElements = ARRAY_SIZE(instance_layout_desc); instance_pipeline_state = create_pipeline_state(context.device, context.root_signature, context.render_target_desc.Format, &vs, &ps, &input_layout); memset(vbv, 0, sizeof(vbv)); vb[0] = create_upload_buffer(context.device, sizeof(positions), positions); vbv[0].BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb[0]); vbv[0].StrideInBytes = sizeof(*positions); vbv[0].SizeInBytes = sizeof(positions); vb[1] = create_upload_buffer(context.device, sizeof(unaligned_colors), unaligned_colors); vbv[1].BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb[1]) + 2 * sizeof(*unaligned_colors); vbv[1].StrideInBytes = sizeof(*unaligned_colors); vbv[1].SizeInBytes = 4 * sizeof(*unaligned_colors); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, ARRAY_SIZE(vbv), vbv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 4, 4, 0, 0); vbv[1].BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb[1]); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, instance_pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, ARRAY_SIZE(vbv), vbv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 4, 4, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); /* There is no one correct result. If we don't crash the GPU, we pass the test. */ check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0xff); ID3D12Resource_Release(vb[1]); ID3D12Resource_Release(vb[0]); ID3D12PipelineState_Release(instance_pipeline_state); destroy_test_context(&context); } void test_zero_vertex_stride(void) { ID3D12PipelineState *instance_pipeline_state; ID3D12GraphicsCommandList *command_list; D3D12_INPUT_LAYOUT_DESC input_layout; D3D12_VERTEX_BUFFER_VIEW vbv[2]; struct test_context_desc desc; struct test_context context; ID3D12CommandQueue *queue; ID3D12Resource *vb[2]; static const D3D12_INPUT_ELEMENT_DESC layout_desc[] = { {"sv_position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"color", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; static const D3D12_INPUT_ELEMENT_DESC instance_layout_desc[] = { {"sv_position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, {"color", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 0}, }; static const DWORD vs_code[] = { #if 0 struct vs_data { float4 pos : SV_POSITION; float4 color : COLOR; }; void main(in struct vs_data vs_input, out struct vs_data vs_output) { vs_output.pos = vs_input.pos; vs_output.color = vs_input.color; } #endif 0x43425844, 0xd5b32785, 0x35332906, 0x4d05e031, 0xf66a58af, 0x00000001, 0x00000144, 0x00000003, 0x0000002c, 0x00000080, 0x000000d4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a, 0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE vs = {vs_code, sizeof(vs_code)}; static const DWORD ps_code[] = { #if 0 struct ps_data { float4 pos : SV_POSITION; float4 color : COLOR; }; float4 main(struct ps_data ps_input) : SV_Target { return ps_input.color; } #endif 0x43425844, 0x89803e59, 0x3f798934, 0xf99181df, 0xf5556512, 0x00000001, 0x000000f4, 0x00000003, 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000038, 0x00000040, 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; static const struct vec4 positions[] = { {-1.0f, -1.0f, 0.0f, 1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f}, { 1.0f, -1.0f, 0.0f, 1.0f}, { 1.0f, 1.0f, 0.0f, 1.0f}, }; static const struct vec4 colors[] = { {0.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {0.5f, 0.5f, 0.5f, 1.0f}, {1.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 1.0f, 1.0f}, }; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; memset(&desc, 0, sizeof(desc)); desc.no_root_signature = true; if (!init_test_context(&context, &desc)) return; command_list = context.list; queue = context.queue; context.root_signature = create_empty_root_signature(context.device, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); input_layout.pInputElementDescs = layout_desc; input_layout.NumElements = ARRAY_SIZE(layout_desc); context.pipeline_state = create_pipeline_state(context.device, context.root_signature, context.render_target_desc.Format, &vs, &ps, &input_layout); input_layout.pInputElementDescs = instance_layout_desc; input_layout.NumElements = ARRAY_SIZE(instance_layout_desc); instance_pipeline_state = create_pipeline_state(context.device, context.root_signature, context.render_target_desc.Format, &vs, &ps, &input_layout); memset(vbv, 0, sizeof(vbv)); vb[0] = create_upload_buffer(context.device, sizeof(positions), positions); vbv[0].BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb[0]); vbv[0].StrideInBytes = sizeof(*positions); vbv[0].SizeInBytes = sizeof(positions); vb[1] = create_upload_buffer(context.device, sizeof(colors), colors); vbv[1].BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb[1]) + 2 * sizeof(*colors); vbv[1].StrideInBytes = 0; vbv[1].SizeInBytes = sizeof(colors); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, ARRAY_SIZE(vbv), vbv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 4, 4, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff808080, 2); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); vbv[1].BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb[1]); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, instance_pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, ARRAY_SIZE(vbv), vbv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 4, 4, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); ID3D12Resource_Release(vb[1]); ID3D12Resource_Release(vb[0]); ID3D12PipelineState_Release(instance_pipeline_state); destroy_test_context(&context); } static void draw_thread_main(void *thread_data) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; struct test_context *context = thread_data; ID3D12GraphicsCommandList *command_list; ID3D12CommandAllocator *allocator; D3D12_CPU_DESCRIPTOR_HANDLE rtv; ID3D12Resource *render_target; ID3D12DescriptorHeap *heap; ID3D12CommandQueue *queue; ID3D12Device *device; unsigned int i; HRESULT hr; queue = context->queue; device = context->device; heap = create_cpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1); rtv = get_cpu_descriptor_handle(context, heap, 0); create_render_target(context, NULL, &render_target, &rtv); hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT, &IID_ID3D12CommandAllocator, (void **)&allocator); ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr); hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list); ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr); for (i = 0; i < 100; ++i) { ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context->root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context->pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context->viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context->scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(render_target, 0, queue, command_list, 0xff00ff00, 0); reset_command_list(command_list, allocator); transition_resource_state(command_list, render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); } ID3D12DescriptorHeap_Release(heap); ID3D12Resource_Release(render_target); ID3D12CommandAllocator_Release(allocator); ID3D12GraphicsCommandList_Release(command_list); } void test_multithread_command_queue_exec(void) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; ID3D12GraphicsCommandList *command_list; struct test_context context; ID3D12CommandQueue *queue; HANDLE threads[10]; unsigned int i; if (!init_test_context(&context, NULL)) return; command_list = context.list; queue = context.queue; for (i = 0; i < ARRAY_SIZE(threads); ++i) { threads[i] = create_thread(draw_thread_main, &context); ok(threads[i], "Failed to create thread %u.\n", i); } for (i = 0; i < 100; ++i) { ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); } for (i = 0; i < ARRAY_SIZE(threads); ++i) ok(join_thread(threads[i]), "Failed to join thread %u.\n", i); destroy_test_context(&context); } void test_command_list_initial_pipeline_state(void) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; ID3D12GraphicsCommandList *command_list; ID3D12PipelineState *pipeline_state; ID3D12CommandAllocator *allocator; struct test_context context; ID3D12CommandQueue *queue; HRESULT hr; static const DWORD ps_code[] = { #if 0 void main(out float4 target : SV_Target) { target = float4(0.0f, 0.25f, 0.5f, 1.0f); } #endif 0x43425844, 0x2f09e5ff, 0xaa135d5e, 0x7860f4b5, 0x5c7b8cbc, 0x00000001, 0x000000b4, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x0000003c, 0x00000050, 0x0000000f, 0x0100086a, 0x03000065, 0x001020f2, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x00000000, 0x3e800000, 0x3f000000, 0x3f800000, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; if (!init_test_context(&context, NULL)) return; queue = context.queue; pipeline_state = create_pipeline_state(context.device, context.root_signature, context.render_target_desc.Format, NULL, &ps, NULL); hr = ID3D12Device_CreateCommandAllocator(context.device, D3D12_COMMAND_LIST_TYPE_DIRECT, &IID_ID3D12CommandAllocator, (void **)&allocator); ok(hr == S_OK, "Failed to create command allocator, hr %#x.\n", hr); hr = ID3D12Device_CreateCommandList(context.device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator, pipeline_state, &IID_ID3D12GraphicsCommandList, (void **)&command_list); ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff804000, 1); hr = ID3D12CommandAllocator_Reset(allocator); ok(hr == S_OK, "Failed to reset command allocator, hr %#x.\n", hr); hr = ID3D12GraphicsCommandList_Reset(command_list, allocator, context.pipeline_state); ok(hr == S_OK, "Failed to reset command list, hr %#x.\n", hr); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); ID3D12CommandAllocator_Release(allocator); ID3D12GraphicsCommandList_Release(command_list); ID3D12PipelineState_Release(pipeline_state); destroy_test_context(&context); } static void prepare_instanced_draw(struct test_context *context) { ID3D12GraphicsCommandList *command_list = context->list; ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context->rtv, false, NULL); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context->root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context->pipeline_state); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context->viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context->scissor_rect); } void test_conditional_rendering(void) { D3D12_ROOT_SIGNATURE_DESC root_signature_desc; ID3D12Resource *conditions, *upload_buffer; ID3D12CommandSignature *command_signature; ID3D12GraphicsCommandList *command_list; D3D12_ROOT_PARAMETER root_parameters[2]; ID3D12Resource *texture, *texture_copy; D3D12_RENDER_TARGET_VIEW_DESC rtv_desc; D3D12_HEAP_PROPERTIES heap_properties; ID3D12PipelineState *pipeline_state; ID3D12RootSignature *root_signature; D3D12_RESOURCE_DESC resource_desc; struct test_context context; ID3D12Resource *buffer, *cb; struct resource_readback rb; ID3D12CommandQueue *queue; unsigned int i; uint32_t value; HRESULT hr; static const uint64_t predicate_args[] = {0, 1, (uint64_t)1 << 32}; static const uint32_t r8g8b8a8_data[] = {0x28384858, 0x39495969}; static const D3D12_DRAW_ARGUMENTS draw_args = {3, 1, 0, 0}; static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const float green[] = {0.0f, 1.0f, 0.0f, 1.0f}; static const float ms_color[] = {0.345f, 0.282f, 0.219f, 0.156f}; static const uint32_t init_value = 0xdeadbeef; static const D3D12_SUBRESOURCE_DATA copy_data[] = { {&r8g8b8a8_data[0], sizeof(r8g8b8a8_data[0]), sizeof(r8g8b8a8_data[0])}, {&r8g8b8a8_data[1], sizeof(r8g8b8a8_data[1]), sizeof(r8g8b8a8_data[1])} }; static const DWORD cs_code[] = { #if 0 cbuffer cb { unsigned int offset; unsigned int value; }; RWByteAddressBuffer b; [numthreads(1, 1, 1)] void main() { b.Store(4 * offset, value); } #endif 0x43425844, 0xaadc5460, 0x88c27e90, 0x2acacf4e, 0x4e06019a, 0x00000001, 0x000000d8, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000084, 0x00050050, 0x00000021, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300009d, 0x0011e000, 0x00000000, 0x02000068, 0x00000001, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x08000029, 0x00100012, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000002, 0x080000a6, 0x0011e012, 0x00000000, 0x0010000a, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x0100003e, }; static const struct { uint32_t offset; uint32_t value; uint32_t uav_offset; } input = {0, 4, 0}; if (!init_test_context(&context, NULL)) return; command_list = context.list; queue = context.queue; if (is_intel_windows_device(context.device)) { skip("Predicated rendering is broken on Intel.\n"); destroy_test_context(&context); return; } conditions = create_default_buffer(context.device, sizeof(predicate_args), D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST); upload_buffer_data(conditions, 0, sizeof(predicate_args), &predicate_args, queue, command_list); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, conditions, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PREDICATION); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); /* Skip draw on zero. */ prepare_instanced_draw(&context); ID3D12GraphicsCommandList_SetPredication(command_list, conditions, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xffffffff, 0); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); /* Skip draw on non-zero. */ prepare_instanced_draw(&context); ID3D12GraphicsCommandList_SetPredication(command_list, conditions, sizeof(uint64_t), D3D12_PREDICATION_OP_NOT_EQUAL_ZERO); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); /* Don't reset predication to test automatic reset on next SetPredication() call. */ transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); ID3D12GraphicsCommandList_SetPredication(command_list, conditions, sizeof(uint64_t), D3D12_PREDICATION_OP_EQUAL_ZERO); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xffffffff, 0); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); /* Skip clear on zero. */ ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); ID3D12GraphicsCommandList_SetPredication(command_list, conditions, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, green, 0, NULL); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); get_texture_readback_with_command_list(context.render_target, 0, &rb, queue, command_list); todo check_readback_data_uint(&rb, NULL, 0xffffffff, 0); release_resource_readback(&rb); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); /* Draw on zero. */ ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); prepare_instanced_draw(&context); ID3D12GraphicsCommandList_SetPredication(command_list, conditions, 0, D3D12_PREDICATION_OP_NOT_EQUAL_ZERO); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); /* Draw on non-zero. */ ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); prepare_instanced_draw(&context); ID3D12GraphicsCommandList_SetPredication(command_list, conditions, sizeof(uint64_t), D3D12_PREDICATION_OP_EQUAL_ZERO); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); /* 64-bit conditional 0x100000000 */ ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); prepare_instanced_draw(&context); ID3D12GraphicsCommandList_SetPredication(command_list, conditions, 2 * sizeof(uint64_t), D3D12_PREDICATION_OP_NOT_EQUAL_ZERO); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); get_texture_readback_with_command_list(context.render_target, 0, &rb, queue, command_list); check_readback_data_uint(&rb, NULL, 0xffffffff, 0); release_resource_readback(&rb); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); /* Direct3D latches the value of the predicate upon beginning predicated rendering. */ buffer = create_default_buffer(context.device, sizeof(predicate_args), D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST); transition_resource_state(command_list, conditions, D3D12_RESOURCE_STATE_PREDICATION, D3D12_RESOURCE_STATE_COPY_SOURCE); ID3D12GraphicsCommandList_CopyResource(command_list, buffer, conditions); transition_resource_state(command_list, buffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PREDICATION); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); prepare_instanced_draw(&context); ID3D12GraphicsCommandList_SetPredication(command_list, buffer, 0, D3D12_PREDICATION_OP_NOT_EQUAL_ZERO); transition_resource_state(command_list, buffer, D3D12_RESOURCE_STATE_PREDICATION, D3D12_RESOURCE_STATE_COPY_DEST); ID3D12GraphicsCommandList_CopyBufferRegion(command_list, buffer, 0, conditions, sizeof(uint64_t), sizeof(uint64_t)); transition_resource_state(command_list, buffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PREDICATION); transition_resource_state(command_list, conditions, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PREDICATION); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); ID3D12Resource_Release(buffer); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); /* SetPredication() and upload buffer. */ upload_buffer = create_upload_buffer(context.device, sizeof(predicate_args), predicate_args); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); prepare_instanced_draw(&context); /* Skip. */ ID3D12GraphicsCommandList_SetPredication(command_list, upload_buffer, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); ID3D12GraphicsCommandList_SetPredication(command_list, upload_buffer, 0, D3D12_PREDICATION_OP_NOT_EQUAL_ZERO); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xffffffff, 0); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); /* ExecuteIndirect(). */ buffer = create_upload_buffer(context.device, sizeof(draw_args), &draw_args); command_signature = create_command_signature(context.device, D3D12_INDIRECT_ARGUMENT_TYPE_DRAW); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); prepare_instanced_draw(&context); /* Skip. */ ID3D12GraphicsCommandList_SetPredication(command_list, conditions, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); ID3D12GraphicsCommandList_ExecuteIndirect(command_list, command_signature, 1, buffer, 0, NULL, 0); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xffffffff, 0); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); prepare_instanced_draw(&context); /* Draw. */ ID3D12GraphicsCommandList_SetPredication(command_list, conditions, 0, D3D12_PREDICATION_OP_NOT_EQUAL_ZERO); ID3D12GraphicsCommandList_ExecuteIndirect(command_list, command_signature, 1, buffer, 0, NULL, 0); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0); ID3D12Resource_Release(buffer); ID3D12CommandSignature_Release(command_signature); reset_command_list(command_list, context.allocator); /* CopyResource(). */ texture = create_default_texture(context.device, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D12_RESOURCE_STATE_COPY_DEST); upload_texture_data(texture, ©_data[0], 1, queue, command_list); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, texture, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE); texture_copy = create_default_texture(context.device, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D12_RESOURCE_STATE_COPY_DEST); upload_texture_data(texture_copy, ©_data[1], 1, queue, command_list); reset_command_list(command_list, context.allocator); /* Skip. */ ID3D12GraphicsCommandList_SetPredication(command_list, conditions, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); ID3D12GraphicsCommandList_CopyResource(command_list, texture_copy, texture); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, texture_copy, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE); get_texture_readback_with_command_list(texture_copy, 0, &rb, queue, command_list); todo check_readback_data_uint(&rb, NULL, r8g8b8a8_data[1], 0); release_resource_readback(&rb); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, texture_copy, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST); /* Copy. */ ID3D12GraphicsCommandList_SetPredication(command_list, conditions, 0, D3D12_PREDICATION_OP_NOT_EQUAL_ZERO); ID3D12GraphicsCommandList_CopyResource(command_list, texture_copy, texture); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, texture_copy, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(texture_copy, 0, queue, command_list, r8g8b8a8_data[0], 0); /* Multisample texture. */ ID3D12Resource_Release(texture); memset(&heap_properties, 0, sizeof(heap_properties)); heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; memset(&resource_desc, 0, sizeof(resource_desc)); resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; resource_desc.Width = 1; resource_desc.Height = 1; resource_desc.DepthOrArraySize = 1; resource_desc.MipLevels = 1; resource_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; resource_desc.SampleDesc.Count = 4; resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; hr = ID3D12Device_CreateCommittedResource(context.device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_RENDER_TARGET, NULL, &IID_ID3D12Resource, (void **)&texture); ok(hr == S_OK, "Failed to create texture, hr %#x.\n", hr); memset(&rtv_desc, 0, sizeof(rtv_desc)); rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS; rtv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; ID3D12Device_CreateRenderTargetView(context.device, texture, &rtv_desc, get_cpu_rtv_handle(&context, context.rtv_heap, 0)); reset_command_list(command_list, context.allocator); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, ms_color, 0, NULL); /* ResolveSubresource(). */ transition_resource_state(command_list, texture_copy, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST); upload_texture_data(texture_copy, ©_data[1], 1, queue, command_list); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, texture_copy, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_RESOLVE_DEST); transition_resource_state(command_list, texture, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE); /* Skip. */ ID3D12GraphicsCommandList_SetPredication(command_list, conditions, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); ID3D12GraphicsCommandList_ResolveSubresource(command_list, texture_copy, 0, texture, 0, DXGI_FORMAT_R8G8B8A8_UNORM); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, texture_copy, D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE); get_texture_readback_with_command_list(texture_copy, 0, &rb, queue, command_list); todo check_readback_data_uint(&rb, NULL, r8g8b8a8_data[1], 0); release_resource_readback(&rb); reset_command_list(command_list, context.allocator); transition_resource_state(command_list, texture_copy, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RESOLVE_DEST); /* Resolve. */ ID3D12GraphicsCommandList_SetPredication(command_list, conditions, 0, D3D12_PREDICATION_OP_NOT_EQUAL_ZERO); ID3D12GraphicsCommandList_ResolveSubresource(command_list, texture_copy, 0, texture, 0, DXGI_FORMAT_R8G8B8A8_UNORM); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_resource_state(command_list, texture_copy, D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(texture_copy, 0, queue, command_list, r8g8b8a8_data[0], 2); reset_command_list(command_list, context.allocator); /* Dispatch(). */ cb = create_upload_buffer(context.device, sizeof(input), &input); buffer = create_default_buffer(context.device, 512, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST); upload_buffer_data(buffer, 0, sizeof(init_value), &init_value, queue, command_list); reset_command_list(command_list, context.allocator); transition_sub_resource_state(command_list, buffer, 0, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; root_parameters[0].Descriptor.ShaderRegister = 0; root_parameters[0].Descriptor.RegisterSpace = 0; root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; root_parameters[1].Descriptor.ShaderRegister = 0; root_parameters[1].Descriptor.RegisterSpace = 0; root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; memset(&root_signature_desc, 0, sizeof(root_signature_desc)); root_signature_desc.NumParameters = 2; root_signature_desc.pParameters = root_parameters; hr = create_root_signature(context.device, &root_signature_desc, &root_signature); ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr); pipeline_state = create_compute_pipeline_state(context.device, root_signature, shader_bytecode(cs_code, sizeof(cs_code))); for (i = 0; i < 2; ++i) { ID3D12GraphicsCommandList_SetPipelineState(command_list, pipeline_state); ID3D12GraphicsCommandList_SetComputeRootSignature(command_list, root_signature); ID3D12GraphicsCommandList_SetComputeRootConstantBufferView(command_list, 0, ID3D12Resource_GetGPUVirtualAddress(cb)); ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(command_list, 1, ID3D12Resource_GetGPUVirtualAddress(buffer)); ID3D12GraphicsCommandList_SetPredication(command_list, conditions, i * sizeof(uint64_t), D3D12_PREDICATION_OP_EQUAL_ZERO); ID3D12GraphicsCommandList_Dispatch(command_list, 1, 1, 1); ID3D12GraphicsCommandList_SetPredication(command_list, NULL, 0, 0); transition_sub_resource_state(command_list, buffer, 0, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE); get_buffer_readback_with_command_list(buffer, DXGI_FORMAT_R32_UINT, &rb, queue, command_list); value = get_readback_uint(&rb, 0, 0, 0); ok(value == (!i ? init_value : input.value), "Got %#x, expected %#x.\n", value, input.value); release_resource_readback(&rb); reset_command_list(command_list, context.allocator); transition_sub_resource_state(command_list, buffer, 0, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); } ID3D12Resource_Release(texture); ID3D12Resource_Release(texture_copy); ID3D12Resource_Release(conditions); ID3D12Resource_Release(cb); ID3D12Resource_Release(buffer); ID3D12Resource_Release(upload_buffer); ID3D12RootSignature_Release(root_signature); ID3D12PipelineState_Release(pipeline_state); destroy_test_context(&context); } void test_write_buffer_immediate(void) { D3D12_WRITEBUFFERIMMEDIATE_PARAMETER parameters[3]; ID3D12GraphicsCommandList2 *command_list2; D3D12_WRITEBUFFERIMMEDIATE_MODE modes[3]; ID3D12GraphicsCommandList *command_list; struct resource_readback rb; struct test_context context; ID3D12CommandQueue *queue; ID3D12Resource *buffer; ID3D12Device *device; unsigned int value; HRESULT hr; static const unsigned int data_values[] = {0xdeadbeef, 0xf00baa, 0xdeadbeef, 0xf00baa}; if (!init_test_context(&context, NULL)) return; device = context.device; command_list = context.list; queue = context.queue; if (FAILED(hr = ID3D12GraphicsCommandList_QueryInterface(command_list, &IID_ID3D12GraphicsCommandList2, (void **)&command_list2))) { skip("ID3D12GraphicsCommandList2 not implemented.\n"); destroy_test_context(&context); return; } buffer = create_default_buffer(device, sizeof(data_values), D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST); upload_buffer_data(buffer, 0, sizeof(data_values), data_values, queue, command_list); reset_command_list(command_list, context.allocator); parameters[0].Dest = ID3D12Resource_GetGPUVirtualAddress(buffer); parameters[0].Value = 0x1020304; parameters[1].Dest = parameters[0].Dest + sizeof(data_values[0]); parameters[1].Value = 0xc0d0e0f; parameters[2].Dest = parameters[0].Dest + sizeof(data_values[0]) * 3; parameters[2].Value = 0x5060708; ID3D12GraphicsCommandList2_WriteBufferImmediate(command_list2, ARRAY_SIZE(parameters), parameters, NULL); hr = ID3D12GraphicsCommandList_Close(command_list); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); exec_command_list(queue, command_list); wait_queue_idle(device, queue); reset_command_list(command_list, context.allocator); get_buffer_readback_with_command_list(buffer, DXGI_FORMAT_R32_UINT, &rb, queue, command_list); value = get_readback_uint(&rb, 0, 0, 0); ok(value == parameters[0].Value, "Got unexpected value %#x, expected %#x.\n", value, parameters[0].Value); value = get_readback_uint(&rb, 1, 0, 0); ok(value == parameters[1].Value, "Got unexpected value %#x, expected %#x.\n", value, parameters[1].Value); value = get_readback_uint(&rb, 2, 0, 0); ok(value == data_values[2], "Got unexpected value %#x, expected %#x.\n", value, data_values[2]); value = get_readback_uint(&rb, 3, 0, 0); ok(value == parameters[2].Value, "Got unexpected value %#x, expected %#x.\n", value, parameters[2].Value); release_resource_readback(&rb); reset_command_list(command_list, context.allocator); parameters[0].Value = 0x2030405; parameters[1].Value = 0xb0c0d0e; parameters[2].Value = 0x708090a; modes[0] = D3D12_WRITEBUFFERIMMEDIATE_MODE_DEFAULT; modes[1] = D3D12_WRITEBUFFERIMMEDIATE_MODE_MARKER_IN; modes[2] = D3D12_WRITEBUFFERIMMEDIATE_MODE_MARKER_OUT; ID3D12GraphicsCommandList2_WriteBufferImmediate(command_list2, ARRAY_SIZE(parameters), parameters, modes); hr = ID3D12GraphicsCommandList_Close(command_list); ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); exec_command_list(queue, command_list); wait_queue_idle(device, queue); reset_command_list(command_list, context.allocator); get_buffer_readback_with_command_list(buffer, DXGI_FORMAT_R32_UINT, &rb, queue, command_list); value = get_readback_uint(&rb, 0, 0, 0); ok(value == parameters[0].Value, "Got unexpected value %#x, expected %#x.\n", value, parameters[0].Value); value = get_readback_uint(&rb, 1, 0, 0); ok(value == parameters[1].Value, "Got unexpected value %#x, expected %#x.\n", value, parameters[1].Value); value = get_readback_uint(&rb, 3, 0, 0); ok(value == parameters[2].Value, "Got unexpected value %#x, expected %#x.\n", value, parameters[2].Value); release_resource_readback(&rb); reset_command_list(command_list, context.allocator); modes[0] = 0x7fffffff; ID3D12GraphicsCommandList2_WriteBufferImmediate(command_list2, ARRAY_SIZE(parameters), parameters, modes); hr = ID3D12GraphicsCommandList_Close(command_list); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); ID3D12Resource_Release(buffer); ID3D12GraphicsCommandList2_Release(command_list2); destroy_test_context(&context); } void test_aliasing_barrier(void) { /* This test mostly serves to verify that validation is clean, * and that we don't crash on weird inputs. There is no particular output we expect to see. */ ID3D12GraphicsCommandList *command_list; D3D12_FEATURE_DATA_D3D12_OPTIONS opts; D3D12_RESOURCE_BARRIER barriers[256]; ID3D12Resource *placed_textures[3]; ID3D12Resource *committed_texture; ID3D12Resource *placed_buffers[3]; D3D12_RESOURCE_DESC texture_desc; ID3D12Resource *committed_buffer; struct test_context_desc desc; struct test_context context; D3D12_HEAP_DESC heap_desc; bool supports_heap_tier_2; ID3D12Heap *buffer_heap; ID3D12Heap *texture_heap; ID3D12Heap *common_heap; ID3D12Device *device; unsigned int i; HRESULT hr; memset(&desc, 0, sizeof(desc)); desc.no_render_target = true; if (!init_test_context(&context, &desc)) return; device = context.device; command_list = context.list; committed_texture = create_default_texture(context.device, 1, 1, DXGI_FORMAT_R32_SINT, D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COMMON); committed_buffer = create_default_buffer(device, 1, D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COMMON); ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_D3D12_OPTIONS, &opts, sizeof(opts)); supports_heap_tier_2 = opts.ResourceHeapTier >= D3D12_RESOURCE_HEAP_TIER_2; memset(&heap_desc, 0, sizeof(heap_desc)); heap_desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; heap_desc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; heap_desc.SizeInBytes = 1024 * 1024; heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; hr = ID3D12Device_CreateHeap(device, &heap_desc, &IID_ID3D12Heap, (void**)&buffer_heap); ok(hr == S_OK, "Failed to create buffer heap hr #%u.\n", hr); heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES; hr = ID3D12Device_CreateHeap(device, &heap_desc, &IID_ID3D12Heap, (void **)&texture_heap); ok(hr == S_OK, "Failed to create buffer heap hr #%u.\n", hr); if (supports_heap_tier_2) { heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES; hr = ID3D12Device_CreateHeap(device, &heap_desc, &IID_ID3D12Heap, (void **)&common_heap); ok(hr == S_OK, "Failed to create buffer heap hr #%u.\n", hr); } else common_heap = NULL; texture_desc.Format = DXGI_FORMAT_R32_SINT; texture_desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; texture_desc.Width = 1; texture_desc.Height = 1; texture_desc.DepthOrArraySize = 1; texture_desc.MipLevels = 1; texture_desc.SampleDesc.Count = 1; texture_desc.SampleDesc.Quality = 0; texture_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; texture_desc.Flags = D3D12_RESOURCE_FLAG_NONE; texture_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; for (i = 0; i < 2; i++) { placed_buffers[i] = create_placed_buffer(device, buffer_heap, 0, 1, D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COMMON); hr = ID3D12Device_CreatePlacedResource(device, texture_heap, 0, &texture_desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, (void **)&placed_textures[i]); ok(hr == S_OK, "Failed to create placed resource. hr = #%u.\n", hr); } placed_buffers[2] = create_placed_buffer(device, supports_heap_tier_2 ? common_heap : buffer_heap, 0, 1, D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COMMON); hr = ID3D12Device_CreatePlacedResource(device, supports_heap_tier_2 ? common_heap : texture_heap, 0, &texture_desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, (void **)&placed_textures[2]); ok(hr == S_OK, "Failed to create placed resource. hr = #%u.\n", hr); for (i = 0; i < ARRAY_SIZE(barriers); i++) { barriers[i].Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING; barriers[i].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; } /* Full barrier */ barriers[0].Aliasing.pResourceBefore = NULL; barriers[0].Aliasing.pResourceAfter = NULL; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, barriers); /* NULL to buffer */ barriers[0].Aliasing.pResourceBefore = NULL; barriers[0].Aliasing.pResourceAfter = placed_buffers[0]; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, barriers); /* NULL to image */ barriers[0].Aliasing.pResourceBefore = NULL; barriers[0].Aliasing.pResourceAfter = placed_textures[0]; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, barriers); /* buffer to NULL */ barriers[0].Aliasing.pResourceBefore = placed_buffers[0]; barriers[0].Aliasing.pResourceAfter = NULL; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, barriers); /* NULL to image */ barriers[0].Aliasing.pResourceBefore = placed_textures[0]; barriers[0].Aliasing.pResourceAfter = NULL; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, barriers); /* buffer to buffer */ barriers[0].Aliasing.pResourceBefore = placed_buffers[0]; barriers[0].Aliasing.pResourceAfter = placed_buffers[1]; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, barriers); /* image to image */ barriers[0].Aliasing.pResourceBefore = placed_textures[0]; barriers[0].Aliasing.pResourceAfter = placed_textures[1]; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, barriers); /* buffer to image */ if (supports_heap_tier_2) { barriers[0].Aliasing.pResourceBefore = placed_buffers[2]; barriers[0].Aliasing.pResourceAfter = placed_textures[2]; ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, barriers); } /* Test spamming lots of redundant image barriers. */ for (i = 0; i < ARRAY_SIZE(barriers); i++) { barriers[i].Aliasing.pResourceBefore = NULL; barriers[i].Aliasing.pResourceAfter = placed_textures[i % 3]; } ID3D12GraphicsCommandList_ResourceBarrier(command_list, ARRAY_SIZE(barriers), barriers); ID3D12Resource_Release(committed_texture); ID3D12Resource_Release(committed_buffer); for (i = 0; i < 3; i++) { ID3D12Resource_Release(placed_textures[i]); ID3D12Resource_Release(placed_buffers[i]); } ID3D12Heap_Release(buffer_heap); ID3D12Heap_Release(texture_heap); if (common_heap) ID3D12Heap_Release(common_heap); destroy_test_context(&context); } static void test_discard_resource_uav_type(bool compute_queue) { static const float white[] = { 1.0f, 1.0f, 1.0f, 1.0f }; D3D12_UNORDERED_ACCESS_VIEW_DESC uav; struct test_context context; ID3D12DescriptorHeap *gpu; ID3D12DescriptorHeap *cpu; ID3D12Resource *resource; if (compute_queue) { /* Creates a COMPUTE list instead of DIRECT. */ if (!init_compute_test_context(&context)) return; } else { if (!init_test_context(&context, NULL)) return; } /* In compute lists, we can discard UAV enabled resources, * and the resource must be in UAV state. */ resource = create_default_texture2d(context.device, 4, 4, 1, 1, DXGI_FORMAT_R32_FLOAT, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); gpu = create_gpu_descriptor_heap(context.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1); cpu = create_cpu_descriptor_heap(context.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1); memset(&uav, 0, sizeof(uav)); uav.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; uav.Format = DXGI_FORMAT_R32_FLOAT; ID3D12Device_CreateUnorderedAccessView(context.device, resource, NULL, &uav, ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(gpu)); ID3D12Device_CreateUnorderedAccessView(context.device, resource, NULL, &uav, ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(cpu)); ID3D12GraphicsCommandList_DiscardResource(context.list, resource, NULL); ID3D12GraphicsCommandList_ClearUnorderedAccessViewFloat(context.list, ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(gpu), ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(cpu), resource, white, 0, NULL); transition_resource_state(context.list, resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_float(resource, 0, context.queue, context.list, 1.0f, 0); ID3D12DescriptorHeap_Release(gpu); ID3D12DescriptorHeap_Release(cpu); ID3D12Resource_Release(resource); destroy_test_context(&context); } void test_discard_resource_uav(void) { vkd3d_test_set_context("Test graphics"); test_discard_resource_uav_type(false); vkd3d_test_set_context("Test compute"); test_discard_resource_uav_type(true); } void test_discard_resource(void) { ID3D12GraphicsCommandList *command_list; D3D12_HEAP_PROPERTIES heap_properties; D3D12_CPU_DESCRIPTOR_HANDLE rtv, dsv; D3D12_RESOURCE_DESC resource_desc; ID3D12DescriptorHeap *rtv_heap; ID3D12DescriptorHeap *dsv_heap; D3D12_DISCARD_REGION ds_region; D3D12_DISCARD_REGION region; struct test_context context; ID3D12Resource *tmp_depth; ID3D12Resource *depth_rt; ID3D12Device *device; ID3D12Resource *rt; HRESULT hr; const float clear_color[] = { 1.0f, 0.0f, 0.0f, 0.0f }; if (!init_test_context(&context, NULL)) return; device = context.device; command_list = context.list; memset(&heap_properties, 0, sizeof(heap_properties)); heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; resource_desc.Alignment = 0; resource_desc.Width = 16; resource_desc.Height = 16; resource_desc.DepthOrArraySize = 2; resource_desc.MipLevels = 1; resource_desc.SampleDesc.Count = 1; resource_desc.SampleDesc.Quality = 0; resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resource_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_RENDER_TARGET, NULL, &IID_ID3D12Resource, (void **)&rt); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; resource_desc.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_DEPTH_WRITE, NULL, &IID_ID3D12Resource, (void **)&depth_rt); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE; resource_desc.Format = DXGI_FORMAT_R32_FLOAT; resource_desc.DepthOrArraySize = 1; hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_COPY_DEST, NULL, &IID_ID3D12Resource, (void **)&tmp_depth); ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); region.NumRects = 0; region.pRects = NULL; region.FirstSubresource = 0; region.NumSubresources = 2; ds_region = region; ds_region.NumSubresources = 4; ID3D12GraphicsCommandList_DiscardResource(context.list, rt, ®ion); ID3D12GraphicsCommandList_DiscardResource(context.list, depth_rt, &ds_region); rtv_heap = create_cpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1); dsv_heap = create_cpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1); rtv = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(rtv_heap); dsv = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(dsv_heap); ID3D12Device_CreateRenderTargetView(device, rt, NULL, rtv); ID3D12Device_CreateDepthStencilView(device, depth_rt, NULL, dsv); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &rtv, false, &dsv); ID3D12GraphicsCommandList_DiscardResource(context.list, rt, ®ion); ID3D12GraphicsCommandList_DiscardResource(context.list, depth_rt, &ds_region); /* Just make sure we don't have validation errors */ hr = ID3D12GraphicsCommandList_Close(context.list); ok(hr == S_OK, "Failed to close command list, hr %#x.\n", hr); hr = ID3D12GraphicsCommandList_Reset(context.list, context.allocator, NULL); ok(hr == S_OK, "Failed to reset command list, hr %#x.\n", hr); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &rtv, false, &dsv); ID3D12GraphicsCommandList_DiscardResource(context.list, rt, ®ion); ID3D12GraphicsCommandList_DiscardResource(context.list, depth_rt, &ds_region); ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv, clear_color, 0, NULL); ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, dsv, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 128, 0, NULL); region.FirstSubresource = 1; region.NumSubresources = 1; ID3D12GraphicsCommandList_DiscardResource(context.list, rt, ®ion); /* Discard stencil aspect and mip 1 of depth aspect. */ ds_region.FirstSubresource = 1; ds_region.NumSubresources = 3; ID3D12GraphicsCommandList_DiscardResource(context.list, depth_rt, &ds_region); /* Ensure that the clear gets executed properly for subresource 0 */ transition_resource_state(context.list, rt, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); transition_resource_state(context.list, depth_rt, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE); check_sub_resource_uint(rt, 0, context.queue, context.list, 0x000000ffu, 0); /* Ensure that the clear gets executed properly for subresource 0 */ hr = ID3D12GraphicsCommandList_Reset(context.list, context.allocator, NULL); { D3D12_TEXTURE_COPY_LOCATION dst_location, src_location; D3D12_BOX src_box; dst_location.SubresourceIndex = 0; dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; dst_location.pResource = tmp_depth; src_location.SubresourceIndex = 0; src_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; src_location.pResource = depth_rt; src_box.left = 0; src_box.right = 16; src_box.top = 0; src_box.bottom = 16; src_box.front = 0; src_box.back = 1; ID3D12GraphicsCommandList_CopyTextureRegion(context.list, &dst_location, 0, 0, 0, &src_location, &src_box); transition_resource_state(context.list, tmp_depth, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE); } check_sub_resource_float(tmp_depth, 0, context.queue, context.list, 1.0f, 0); ID3D12Resource_Release(rt); ID3D12Resource_Release(depth_rt); ID3D12Resource_Release(tmp_depth); ID3D12DescriptorHeap_Release(rtv_heap); ID3D12DescriptorHeap_Release(dsv_heap); destroy_test_context(&context); } void test_root_parameter_preservation(void) { D3D12_ROOT_SIGNATURE_DESC root_signature_desc; D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc; ID3D12RootSignature *root_signature; D3D12_ROOT_PARAMETER root_parameter; ID3D12PipelineState *graphics_pso; ID3D12PipelineState *compute_pso; struct test_context_desc desc; struct test_context context; struct resource_readback rb; ID3D12Resource *buffer; uint32_t value; HRESULT hr; static const DWORD ps_code[] = { #if 0 RWStructuredBuffer RWBuf : register(u1); float4 main() : SV_Target { uint v; InterlockedAdd(RWBuf[0], 100, v); return 1.0.xxxx; } #endif 0x43425844, 0x752ce8e8, 0x84d20946, 0xf5cbf13c, 0x37b624ad, 0x00000001, 0x000000ec, 0x00000003, 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000074, 0x00000050, 0x0000001d, 0x0100086a, 0x0400009e, 0x0011e000, 0x00000001, 0x00000004, 0x03000065, 0x001020f2, 0x00000000, 0x0a0000ad, 0x0011e000, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004001, 0x00000064, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; static const DWORD cs_code[] = { #if 0 RWStructuredBuffer RWBuf : register(u1); [numthreads(1, 1, 1)] void main() { uint v; InterlockedAdd(RWBuf[0], 1, v); } #endif 0x43425844, 0x010d2839, 0x4ca90409, 0x945bf22a, 0x52d288e5, 0x00000001, 0x000000ac, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000058, 0x00050050, 0x00000016, 0x0100086a, 0x0400009e, 0x0011e000, 0x00000001, 0x00000004, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x0a0000ad, 0x0011e000, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004001, 0x00000001, 0x0100003e, }; static const D3D12_SHADER_BYTECODE cs = {cs_code, sizeof(cs_code)}; memset(&desc, 0, sizeof(desc)); desc.rt_width = 1; desc.rt_height = 1; desc.rt_format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.rt_descriptor_count = 1; desc.sample_desc.Count = 1; desc.rt_array_size = 1; desc.no_pipeline = true; desc.no_root_signature = true; if (!init_test_context(&context, &desc)) return; memset(&root_signature_desc, 0, sizeof(root_signature_desc)); memset(&root_parameter, 0, sizeof(root_parameter)); root_signature_desc.NumParameters = 1; root_signature_desc.pParameters = &root_parameter; root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; root_parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; root_parameter.Descriptor.ShaderRegister = 1; hr = create_root_signature(context.device, &root_signature_desc, &root_signature); ok(SUCCEEDED(hr), "Failed to create root signature, hr = #%x.\n", hr); init_pipeline_state_desc(&pso_desc, root_signature, desc.rt_format, NULL, &ps, NULL); hr = ID3D12Device_CreateGraphicsPipelineState(context.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&graphics_pso); ok(SUCCEEDED(hr), "Failed to create PSO, hr = #%x.\n", hr); compute_pso = create_compute_pipeline_state(context.device, root_signature, cs); buffer = create_default_buffer(context.device, 4096, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); ID3D12GraphicsCommandList_SetComputeRootSignature(context.list, root_signature); ID3D12GraphicsCommandList_SetGraphicsRootSignature(context.list, root_signature); ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(context.list, 0, ID3D12Resource_GetGPUVirtualAddress(buffer)); ID3D12GraphicsCommandList_SetGraphicsRootUnorderedAccessView(context.list, 0, ID3D12Resource_GetGPUVirtualAddress(buffer) + 4); ID3D12GraphicsCommandList_SetPipelineState(context.list, compute_pso); ID3D12GraphicsCommandList_Dispatch(context.list, 4, 1, 1); uav_barrier(context.list, buffer); ID3D12GraphicsCommandList_SetPipelineState(context.list, graphics_pso); ID3D12GraphicsCommandList_IASetPrimitiveTopology(context.list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D12GraphicsCommandList_OMSetRenderTargets(context.list, 1, &context.rtv, TRUE, NULL); ID3D12GraphicsCommandList_RSSetViewports(context.list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(context.list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_DrawInstanced(context.list, 3, 1, 0, 0); uav_barrier(context.list, buffer); /* We never touched root signature or root parameters, but verify that we correctly update push constants here. */ ID3D12GraphicsCommandList_SetPipelineState(context.list, compute_pso); ID3D12GraphicsCommandList_Dispatch(context.list, 4, 1, 1); transition_resource_state(context.list, buffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE); get_buffer_readback_with_command_list(buffer, DXGI_FORMAT_UNKNOWN, &rb, context.queue, context.list); value = get_readback_uint(&rb, 0, 0, 0); ok(value == 8, "Value %u != 8.\n", value); value = get_readback_uint(&rb, 1, 0, 0); ok(value == 100, "Value %u != 100.\n", value); release_resource_readback(&rb); ID3D12Resource_Release(buffer); ID3D12RootSignature_Release(root_signature); ID3D12PipelineState_Release(graphics_pso); ID3D12PipelineState_Release(compute_pso); destroy_test_context(&context); } static void test_cbv_hoisting(bool use_dxil) { D3D12_VERSIONED_ROOT_SIGNATURE_DESC root_signature_desc; D3D12_ROOT_PARAMETER1 root_parameters[2]; D3D12_DESCRIPTOR_RANGE1 table_ranges[4]; unsigned int i, base_shader_register; ID3D12RootSignature *root_signature; uint32_t cbuffer_data[64 * 4]; struct test_context context; struct resource_readback rb; ID3D12DescriptorHeap *desc; ID3D12PipelineState *pso; ID3D12Resource *wbuffer; ID3D12Resource *rbuffer; uint32_t value; HRESULT hr; #if 0 // Can be hoisted. cbuffer cbuf0 : register(b0) { uint v0; }; struct C { uint v; }; // Can be hoisted. ConstantBuffer cbuf1[1]: register(b1); // Cannot be hoisted. ConstantBuffer cbufs[2] : register(b2); RWByteAddressBuffer RWBuf : register(u0); [numthreads(4, 1, 1)] void main(uint thr : SV_DispatchThreadID) { uint wval; if (thr == 0) wval = v0; else if (thr == 2) wval = cbufs[0].v; else if (thr == 3) wval = cbufs[1].v; else { // Verify that we can convert this to a plain descriptor, even with weird indexing into array size of 1. // Array size of 1 means we have to access one descriptor. wval = cbuf1[NonUniformResourceIndex(thr - 1)].v; } RWBuf.Store(4 * thr, wval); } #endif static const DWORD cs_code_dxbc[] = { 0x43425844, 0x0ff40a34, 0xe72ddcb6, 0x2821e5e5, 0x57c71636, 0x00000001, 0x00000224, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000001d0, 0x00050051, 0x00000074, 0x0100086a, 0x07000059, 0x00308e46, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x07000859, 0x00308e46, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x07000059, 0x00308e46, 0x00000002, 0x00000002, 0x00000003, 0x00000001, 0x00000000, 0x0600009d, 0x0031ee46, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000004, 0x00000001, 0x00000001, 0x0200001f, 0x0002000a, 0x07000036, 0x00100022, 0x00000000, 0x0030800a, 0x00000000, 0x00000000, 0x00000000, 0x01000012, 0x06000020, 0x00100012, 0x00000000, 0x0002000a, 0x00004001, 0x00000002, 0x0304001f, 0x0010000a, 0x00000000, 0x07000036, 0x00100022, 0x00000000, 0x0030800a, 0x00000002, 0x00000002, 0x00000000, 0x01000012, 0x06000020, 0x00100012, 0x00000000, 0x0002000a, 0x00004001, 0x00000003, 0x0304001f, 0x0010000a, 0x00000000, 0x07000036, 0x00100022, 0x00000000, 0x0030800a, 0x00000002, 0x00000003, 0x00000000, 0x01000012, 0x0600001e, 0x00100012, 0x00000000, 0x0002000a, 0x00004001, 0xffffffff, 0x0a000036, 0x00100022, 0x00000000, 0x8630800a, 0x00020001, 0x00000001, 0x00000001, 0x0010000a, 0x00000000, 0x00000000, 0x01000015, 0x01000015, 0x01000015, 0x06000029, 0x00100012, 0x00000000, 0x0002000a, 0x00004001, 0x00000002, 0x080000a6, 0x0021e012, 0x00000000, 0x00000000, 0x0010000a, 0x00000000, 0x0010001a, 0x00000000, 0x0100003e, }; static const BYTE cs_code_dxil[] = { 0x44, 0x58, 0x42, 0x43, 0x3c, 0x44, 0x94, 0x59, 0x48, 0xd4, 0x45, 0xa8, 0x23, 0x30, 0x16, 0x51, 0x75, 0x5c, 0x04, 0x1f, 0x01, 0x00, 0x00, 0x00, 0x08, 0x07, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x7c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x18, 0x06, 0x00, 0x00, 0x60, 0x00, 0x05, 0x00, 0x86, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x7d, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x01, 0xd5, 0x06, 0x62, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x90, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x7c, 0x23, 0x00, 0x25, 0x00, 0x14, 0xe6, 0x08, 0xc0, 0xa0, 0x0c, 0x63, 0x0c, 0x22, 0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, 0x15, 0x2b, 0x31, 0xf9, 0xc8, 0x6d, 0x23, 0x62, 0x8c, 0x31, 0xe6, 0x08, 0x10, 0x3a, 0xf7, 0x0c, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0x21, 0xd0, 0x0c, 0x0b, 0x81, 0x02, 0x54, 0x08, 0x33, 0xd2, 0x20, 0x35, 0x47, 0x10, 0x14, 0x23, 0x8d, 0x33, 0x06, 0xa3, 0x56, 0x14, 0x30, 0xd2, 0x18, 0x63, 0x8c, 0x71, 0xe8, 0x0d, 0x04, 0x9c, 0x26, 0x4d, 0x11, 0x25, 0x4c, 0xfe, 0x0a, 0x6f, 0xd8, 0x44, 0x68, 0xc3, 0x10, 0x11, 0x92, 0xb4, 0x51, 0x45, 0x41, 0x44, 0x28, 0x18, 0x24, 0xaf, 0x10, 0x02, 0xaa, 0xa0, 0x51, 0x30, 0x88, 0x1e, 0x22, 0x4d, 0x11, 0x25, 0x4c, 0x3e, 0x87, 0x82, 0x91, 0x01, 0xf6, 0x0a, 0x21, 0xa0, 0x8a, 0x1a, 0x05, 0x97, 0xf0, 0x15, 0x42, 0x40, 0x15, 0x12, 0x0a, 0x6c, 0x0a, 0x68, 0xda, 0x73, 0x04, 0xa0, 0x30, 0x05, 0x00, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x04, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x14, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x79, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0b, 0x04, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a, 0x25, 0x30, 0x02, 0x50, 0x08, 0xc5, 0x50, 0x16, 0x45, 0x40, 0x6c, 0x04, 0x80, 0x7a, 0x81, 0x50, 0x9d, 0x01, 0xa0, 0x3c, 0x03, 0x40, 0x7c, 0x06, 0x80, 0xe6, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x88, 0x0c, 0x6f, 0xec, 0xed, 0x4d, 0x0c, 0x44, 0x06, 0x26, 0x26, 0xc7, 0x05, 0xa6, 0xc6, 0x05, 0x06, 0x66, 0x43, 0x10, 0x4c, 0x10, 0x86, 0x62, 0x82, 0x30, 0x18, 0x1b, 0x84, 0x81, 0x98, 0x20, 0x0c, 0xc7, 0x06, 0x61, 0x30, 0x28, 0x8c, 0xcd, 0x4d, 0x10, 0x06, 0x64, 0xc3, 0x80, 0x24, 0xc4, 0x04, 0x61, 0x82, 0x08, 0x4c, 0x10, 0x86, 0x64, 0x82, 0xc0, 0x2c, 0x1b, 0x16, 0x62, 0x61, 0x08, 0x62, 0x68, 0x1c, 0xc7, 0x01, 0x36, 0x04, 0xcf, 0x04, 0xa1, 0x6a, 0x36, 0x20, 0x44, 0xc4, 0x10, 0xc4, 0x60, 0x00, 0x13, 0x84, 0xcc, 0xd9, 0x80, 0x0c, 0x13, 0x43, 0x0c, 0x83, 0x01, 0x4c, 0x10, 0x06, 0x65, 0x82, 0xc0, 0x3d, 0x1b, 0x90, 0xca, 0x62, 0x88, 0xaa, 0x32, 0x80, 0x0d, 0x83, 0x44, 0x5d, 0x1b, 0x08, 0x00, 0xc2, 0x80, 0x09, 0x82, 0x00, 0x6c, 0x00, 0x36, 0x0c, 0xc4, 0xb6, 0x6d, 0x08, 0xb8, 0x0d, 0xc3, 0xa0, 0x75, 0x24, 0xda, 0xc2, 0xd2, 0xdc, 0x26, 0x08, 0x1d, 0xb3, 0x61, 0x30, 0x86, 0x61, 0x03, 0x41, 0x80, 0x81, 0x11, 0x06, 0x1b, 0x0a, 0xed, 0x03, 0x32, 0x31, 0xa8, 0xc2, 0xc6, 0x66, 0xd7, 0xe6, 0x92, 0x46, 0x56, 0xe6, 0x46, 0x37, 0x25, 0x08, 0xaa, 0x90, 0xe1, 0xb9, 0xd8, 0x95, 0xc9, 0xcd, 0xa5, 0xbd, 0xb9, 0x4d, 0x09, 0x88, 0x26, 0x64, 0x78, 0x2e, 0x76, 0x61, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x02, 0xa3, 0x0e, 0x19, 0x9e, 0xcb, 0x1c, 0x5a, 0x18, 0x59, 0x99, 0x5c, 0xd3, 0x1b, 0x59, 0x19, 0xdb, 0x94, 0x20, 0x29, 0x43, 0x86, 0xe7, 0x22, 0x57, 0x36, 0xf7, 0x56, 0x27, 0x37, 0x56, 0x36, 0x37, 0x25, 0xc0, 0x2a, 0x91, 0xe1, 0xb9, 0xd0, 0xe5, 0xc1, 0x95, 0x05, 0xb9, 0xb9, 0xbd, 0xd1, 0x85, 0xd1, 0xa5, 0xbd, 0xb9, 0xcd, 0x4d, 0x09, 0xba, 0x3a, 0x64, 0x78, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x53, 0x02, 0x31, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x8c, 0xcc, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x74, 0x60, 0x07, 0x37, 0x90, 0x87, 0x72, 0x98, 0x87, 0x77, 0xa8, 0x07, 0x79, 0x18, 0x87, 0x72, 0x70, 0x83, 0x70, 0xa0, 0x07, 0x7a, 0x90, 0x87, 0x74, 0x10, 0x87, 0x7a, 0xa0, 0x87, 0x72, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x46, 0x50, 0x0d, 0x97, 0xef, 0x3c, 0x7e, 0x40, 0x15, 0x05, 0x11, 0xb1, 0x93, 0x13, 0x11, 0x3e, 0x72, 0xdb, 0x26, 0xb0, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x10, 0x50, 0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25, 0x61, 0x00, 0x02, 0xe6, 0x23, 0xb7, 0x6d, 0x03, 0xd2, 0x70, 0xf9, 0xce, 0xe3, 0x0b, 0x11, 0x01, 0x4c, 0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0x80, 0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0xd3, 0x11, 0x11, 0xc0, 0x20, 0x0e, 0x3e, 0x72, 0xdb, 0x06, 0x40, 0x30, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x13, 0x04, 0x48, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x4a, 0xae, 0xec, 0x66, 0x00, 0xca, 0xa0, 0x74, 0x03, 0x6a, 0xa0, 0x14, 0x03, 0xe8, 0x14, 0x41, 0x09, 0x00, 0x00, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0xd0, 0x5c, 0x49, 0x40, 0x51, 0xcf, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x34, 0x98, 0x32, 0x58, 0x16, 0x34, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x4d, 0xb6, 0x10, 0x96, 0x15, 0x8d, 0x18, 0x24, 0x00, 0x08, 0x82, 0x41, 0xa3, 0x31, 0xc5, 0x94, 0x48, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0xd0, 0x6c, 0x8d, 0x41, 0x51, 0xd3, 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x10, 0x9e, 0x92, 0x0d, 0x37, 0x04, 0x1a, 0x18, 0xcc, 0x32, 0x04, 0x42, 0x30, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0xca, 0xf7, 0x14, 0xdb, 0x68, 0x42, 0x00, 0xcc, 0x12, 0x1c, 0xc3, 0x0d, 0x44, 0x06, 0x06, 0xb3, 0x0c, 0x03, 0x11, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0x81, 0x22, 0x06, 0x92, 0xe1, 0x8d, 0x26, 0x04, 0xc0, 0x2c, 0xc1, 0x31, 0xdc, 0x70, 0x48, 0x60, 0x30, 0xcb, 0x50, 0x18, 0xc1, 0x88, 0xc1, 0x01, 0x80, 0x20, 0x18, 0x28, 0x65, 0x50, 0x29, 0x61, 0x30, 0x9a, 0x10, 0x00, 0xb3, 0x04, 0x47, 0x29, 0x13, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0x81, 0x82, 0x06, 0xd8, 0x13, 0x8c, 0x26, 0x04, 0xc0, 0x2c, 0xc1, 0x31, 0x50, 0x32, 0x50, 0x81, 0x33, 0x20, 0x85, 0x60, 0x94, 0x33, 0x06, 0x37, 0x62, 0xd0, 0x00, 0x20, 0x08, 0x06, 0x8f, 0x1a, 0x5c, 0x54, 0xb0, 0x09, 0xdb, 0xb6, 0x55, 0x08, 0x00, 0x00, 0x00, 0x00, }; const D3D12_SHADER_BYTECODE cs = {use_dxil ? (const void*)cs_code_dxil : (const void*)cs_code_dxbc, use_dxil ? sizeof(cs_code_dxil) : sizeof(cs_code_dxbc)}; if (!init_compute_test_context(&context)) return; if (use_dxil && !context_supports_dxil(&context)) { destroy_test_context(&context); return; } memset(&root_signature_desc, 0, sizeof(root_signature_desc)); memset(root_parameters, 0, sizeof(root_parameters)); memset(table_ranges, 0, sizeof(table_ranges)); root_signature_desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; root_signature_desc.Desc_1_1.NumParameters = ARRAY_SIZE(root_parameters); root_signature_desc.Desc_1_1.pParameters = root_parameters; root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; root_parameters[0].DescriptorTable.NumDescriptorRanges = ARRAY_SIZE(table_ranges); root_parameters[0].DescriptorTable.pDescriptorRanges = table_ranges; root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV; root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; base_shader_register = 0; for (i = 0; i < ARRAY_SIZE(table_ranges); i++) { table_ranges[i].NumDescriptors = i >= 2 ? 2 : 1; table_ranges[i].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; table_ranges[i].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS; table_ranges[i].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; table_ranges[i].BaseShaderRegister = base_shader_register; base_shader_register += table_ranges[i].NumDescriptors; } hr = create_versioned_root_signature(context.device, &root_signature_desc, &root_signature); ok(SUCCEEDED(hr), "Failed to create root signature, hr = #%x.\n", hr); pso = create_compute_pipeline_state(context.device, root_signature, cs); memset(cbuffer_data, 0, sizeof(cbuffer_data)); for (i = 0; i < ARRAY_SIZE(table_ranges); i++) cbuffer_data[i * 64] = i; rbuffer = create_upload_buffer(context.device, sizeof(cbuffer_data), cbuffer_data); wbuffer = create_default_buffer(context.device, ARRAY_SIZE(table_ranges) * sizeof(uint32_t), D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); desc = create_gpu_descriptor_heap(context.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, ARRAY_SIZE(table_ranges)); for (i = 0; i < ARRAY_SIZE(table_ranges); i++) { D3D12_CONSTANT_BUFFER_VIEW_DESC cbv; D3D12_CPU_DESCRIPTOR_HANDLE handle; handle = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(desc); handle.ptr += i * ID3D12Device_GetDescriptorHandleIncrementSize(context.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); cbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(rbuffer) + 256 * i; cbv.SizeInBytes = 256; ID3D12Device_CreateConstantBufferView(context.device, &cbv, handle); } ID3D12GraphicsCommandList_SetDescriptorHeaps(context.list, 1, &desc); ID3D12GraphicsCommandList_SetPipelineState(context.list, pso); ID3D12GraphicsCommandList_SetComputeRootSignature(context.list, root_signature); ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(context.list, 0, ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(desc)); ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView(context.list, 1, ID3D12Resource_GetGPUVirtualAddress(wbuffer)); ID3D12GraphicsCommandList_Dispatch(context.list, 1, 1, 1); transition_resource_state(context.list, wbuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE); get_buffer_readback_with_command_list(wbuffer, DXGI_FORMAT_UNKNOWN, &rb, context.queue, context.list); for (i = 0; i < ARRAY_SIZE(table_ranges); i++) { value = get_readback_uint(&rb, i, 0, 0); ok(value == i, "Value %u != %u.\n", value, i); } release_resource_readback(&rb); ID3D12Resource_Release(wbuffer); ID3D12Resource_Release(rbuffer); ID3D12RootSignature_Release(root_signature); ID3D12PipelineState_Release(pso); ID3D12DescriptorHeap_Release(desc); destroy_test_context(&context); } void test_cbv_hoisting_sm51(void) { test_cbv_hoisting(false); } void test_cbv_hoisting_dxil(void) { test_cbv_hoisting(true); } static void test_conservative_rasterization(bool use_dxil) { ID3D12PipelineState *pipeline_conservative_underestimate; ID3D12PipelineState *pipeline_conservative_overestimate; ID3D12PipelineState *pipeline_conservative_off; D3D12_ROOT_SIGNATURE_DESC root_signature_desc; D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc; ID3D12PipelineState *pipeline_stencil_test; D3D12_FEATURE_DATA_D3D12_OPTIONS options; ID3D12GraphicsCommandList *command_list; D3D12_INPUT_LAYOUT_DESC input_layout; ID3D12RootSignature *root_signature; struct depth_stencil_resource ds; D3D12_QUERY_HEAP_DESC heap_desc; struct test_context_desc desc; ID3D12Resource *vb, *readback; D3D12_VERTEX_BUFFER_VIEW vbv; struct test_context context; ID3D12QueryHeap *query_heap; struct resource_readback rb; ID3D12CommandQueue *queue; uint64_t value; unsigned int i; HRESULT hr; #if 0 float4 main(float4 p : POSITION) : SV_Position { return p; } #endif static const DWORD vs_dxbc[] = { 0x43425844, 0x92767590, 0x06a6dba7, 0x0ae078b2, 0x7b5eb8f6, 0x00000001, 0x000000d8, 0x00000003, 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x7469736f, 0x006e6f69, 0x52444853, 0x0000003c, 0x00010040, 0x0000000f, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, }; static const BYTE vs_dxil[] = { 0x44, 0x58, 0x42, 0x43, 0x48, 0xc5, 0x2e, 0x8b, 0x11, 0x71, 0xe3, 0x06, 0xc8, 0x49, 0x0f, 0x0b, 0x1a, 0x84, 0x82, 0x61, 0x01, 0x00, 0x00, 0x00, 0xe9, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x50, 0x53, 0x56, 0x30, 0x78, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x03, 0x03, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0xa8, 0x04, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x2a, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x01, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x30, 0x23, 0x00, 0x25, 0x00, 0x8a, 0x19, 0x80, 0x39, 0x02, 0x30, 0x98, 0x23, 0x40, 0x8a, 0x31, 0x44, 0x54, 0x44, 0x56, 0x0c, 0x20, 0xa2, 0x1a, 0xc2, 0x81, 0x80, 0x34, 0x20, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x02, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0xa2, 0x12, 0x18, 0x01, 0x28, 0x84, 0x62, 0xa0, 0x2a, 0x89, 0x11, 0x80, 0x42, 0x28, 0x03, 0xda, 0xb1, 0x0c, 0x82, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x83, 0x0c, 0x6f, 0x0c, 0x24, 0xc6, 0x45, 0x66, 0x43, 0x10, 0x4c, 0x10, 0x88, 0x61, 0x82, 0x40, 0x10, 0x1b, 0x84, 0x81, 0x98, 0x20, 0x10, 0xc5, 0x06, 0x61, 0x30, 0x28, 0xd8, 0xcd, 0x4d, 0x10, 0x08, 0x63, 0xc3, 0x80, 0x24, 0xc4, 0x04, 0x41, 0x00, 0x36, 0x00, 0x1b, 0x06, 0x82, 0x61, 0x36, 0x04, 0xcd, 0x86, 0x61, 0x58, 0x9c, 0x09, 0xc2, 0xb2, 0x6c, 0x08, 0x20, 0x12, 0x6d, 0x61, 0x69, 0x6e, 0x44, 0xa0, 0x9e, 0xa6, 0x92, 0xa8, 0x92, 0x9e, 0x9c, 0x26, 0x08, 0xc5, 0x31, 0x41, 0x28, 0x90, 0x0d, 0x01, 0x31, 0x41, 0x28, 0x92, 0x0d, 0x0b, 0x31, 0x51, 0x95, 0x55, 0x0d, 0x17, 0x51, 0x01, 0x1b, 0x02, 0x8c, 0xcb, 0x94, 0xd5, 0x17, 0xd4, 0xdb, 0x5c, 0x1a, 0x5d, 0xda, 0x9b, 0xdb, 0x04, 0xa1, 0x50, 0x36, 0x2c, 0x84, 0x46, 0x6d, 0xd6, 0x35, 0x5c, 0x44, 0x05, 0x6c, 0x08, 0xb8, 0x0d, 0x43, 0xd6, 0x01, 0x1b, 0x8a, 0x45, 0xf2, 0x00, 0xa0, 0x0a, 0x1b, 0x9b, 0x5d, 0x9b, 0x4b, 0x1a, 0x59, 0x99, 0x1b, 0xdd, 0x94, 0x20, 0xa8, 0x42, 0x86, 0xe7, 0x62, 0x57, 0x26, 0x37, 0x97, 0xf6, 0xe6, 0x36, 0x25, 0x20, 0x9a, 0x90, 0xe1, 0xb9, 0xd8, 0x85, 0xb1, 0xd9, 0x95, 0xc9, 0x4d, 0x09, 0x8c, 0x3a, 0x64, 0x78, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x53, 0x82, 0xa4, 0x12, 0x19, 0x9e, 0x0b, 0x5d, 0x1e, 0x5c, 0x59, 0x90, 0x9b, 0xdb, 0x1b, 0x5d, 0x18, 0x5d, 0xda, 0x9b, 0xdb, 0xdc, 0x94, 0xc0, 0xa9, 0x43, 0x86, 0xe7, 0x62, 0x97, 0x56, 0x76, 0x97, 0x44, 0x36, 0x45, 0x17, 0x46, 0x57, 0x36, 0x25, 0x80, 0xea, 0x90, 0xe1, 0xb9, 0x94, 0xb9, 0xd1, 0xc9, 0xe5, 0x41, 0xbd, 0xa5, 0xb9, 0xd1, 0xcd, 0x4d, 0x09, 0x3c, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0x03, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x16, 0x30, 0x0d, 0x97, 0xef, 0x3c, 0xfe, 0xe2, 0x00, 0x83, 0xd8, 0x3c, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x00, 0x04, 0x03, 0x20, 0x8d, 0x09, 0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x4d, 0x4e, 0x44, 0xa0, 0xd4, 0xf4, 0x50, 0x93, 0x5f, 0xdc, 0x36, 0x00, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x44, 0x33, 0x00, 0xa5, 0x40, 0x55, 0x02, 0x45, 0x00, 0x00, 0x00, 0x00, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x60, 0x3c, 0x0b, 0xc3, 0x20, 0xc4, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x10, 0xd3, 0x34, 0x43, 0x31, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x46, 0xd4, 0x38, 0xce, 0x60, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x81, 0x21, 0x39, 0xcf, 0x93, 0x1c, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x80, 0x48, 0x07, 0x04, 0x31, 0xc4, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xd2, 0x01, 0x41, 0xc6, 0x30, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x88, 0x74, 0x40, 0x50, 0x21, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x22, 0x1d, 0x10, 0xa4, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, }; const D3D12_SHADER_BYTECODE vs = { use_dxil ? (const void*)vs_dxil : (const void*)vs_dxbc, use_dxil ? sizeof(vs_dxil) : sizeof(vs_dxbc), }; #if 0 void main() { } #endif static const DWORD ps_dxbc[] = { 0x43425844, 0x499d4ed5, 0xbbe2842c, 0x179313ee, 0xde5cd5d9, 0x00000001, 0x00000064, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000010, 0x00000050, 0x00000004, 0x0100086a, 0x0100003e, }; static const BYTE ps_dxil[] = { 0x44, 0x58, 0x42, 0x43, 0xe9, 0xaf, 0xe0, 0x0e, 0x69, 0x4d, 0x92, 0x13, 0xf2, 0x58, 0xdf, 0x54, 0xf6, 0x12, 0x3e, 0x16, 0x01, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x38, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x4c, 0x03, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x0c, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x64, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x32, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x91, 0x21, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x19, 0x46, 0x06, 0x89, 0x20, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x22, 0xc8, 0x08, 0x20, 0x64, 0x85, 0x04, 0x93, 0x21, 0xa4, 0x84, 0x04, 0x93, 0x21, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x86, 0x8c, 0x0b, 0x84, 0x64, 0x4c, 0x10, 0x14, 0x23, 0x00, 0x25, 0x00, 0x65, 0x20, 0x60, 0x8e, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x0c, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x62, 0x09, 0x8c, 0x00, 0x14, 0x42, 0x31, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x83, 0x0c, 0x6f, 0x0c, 0x24, 0xc6, 0x45, 0x66, 0x43, 0x10, 0x4c, 0x10, 0x88, 0x60, 0x82, 0x40, 0x08, 0x1b, 0x84, 0x81, 0x98, 0x20, 0x10, 0xc3, 0x06, 0x61, 0x30, 0x28, 0xc0, 0xcd, 0x4d, 0x10, 0x08, 0x62, 0xc3, 0x80, 0x24, 0xc4, 0x04, 0x41, 0x00, 0x36, 0x00, 0x1b, 0x86, 0x81, 0x61, 0x36, 0x04, 0xcd, 0x86, 0x61, 0x58, 0x1c, 0x12, 0x6d, 0x61, 0x69, 0x6e, 0x1b, 0x8a, 0x05, 0x02, 0x00, 0xa0, 0x0a, 0x1b, 0x9b, 0x5d, 0x9b, 0x4b, 0x1a, 0x59, 0x99, 0x1b, 0xdd, 0x94, 0x20, 0xa8, 0x42, 0x86, 0xe7, 0x62, 0x57, 0x26, 0x37, 0x97, 0xf6, 0xe6, 0x36, 0x25, 0x20, 0x9a, 0x90, 0xe1, 0xb9, 0xd8, 0x85, 0xb1, 0xd9, 0x95, 0xc9, 0x4d, 0x09, 0x8c, 0x3a, 0x64, 0x78, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x53, 0x82, 0xa4, 0x12, 0x19, 0x9e, 0x0b, 0x5d, 0x1e, 0x5c, 0x59, 0x90, 0x9b, 0xdb, 0x1b, 0x5d, 0x18, 0x5d, 0xda, 0x9b, 0xdb, 0xdc, 0x94, 0xc0, 0xa9, 0x43, 0x86, 0xe7, 0x52, 0xe6, 0x46, 0x27, 0x97, 0x07, 0xf5, 0x96, 0xe6, 0x46, 0x37, 0x37, 0x25, 0x80, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0x03, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x30, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, }; const D3D12_SHADER_BYTECODE ps = { use_dxil ? (const void*)ps_dxil : (const void*)ps_dxbc, use_dxil ? sizeof(ps_dxil) : sizeof(ps_dxbc), }; #if 0 void main(in uint ic : SV_InnerCoverage) { if (ic == 0) discard; } #endif static const DWORD ps_underestimate_dxbc[] = { 0x43425844, 0x8f1e8d53, 0x05b0f2c6, 0xe8d795db, 0xc9e0ffef, 0x00000001, 0x00000088, 0x00000004, 0x00000030, 0x00000040, 0x00000050, 0x00000078, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000020, 0x00000050, 0x00000008, 0x0100086a, 0x0200005f, 0x0002a001, 0x0200000d, 0x0002a00a, 0x0100003e, 0x30494653, 0x00000008, 0x00000400, 0x00000000, }; static const BYTE ps_underestimate_dxil[] = { 0x44, 0x58, 0x42, 0x43, 0x44, 0xdd, 0x61, 0xc1, 0x16, 0xde, 0xe1, 0x6b, 0x12, 0xae, 0x63, 0xf3, 0xd8, 0x99, 0x57, 0x60, 0x01, 0x00, 0x00, 0x00, 0xb0, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x38, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x04, 0x04, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xec, 0x03, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x01, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x30, 0x23, 0x00, 0x25, 0x00, 0x8a, 0x39, 0x02, 0x30, 0x28, 0xc2, 0x0c, 0xd1, 0x1c, 0x41, 0x50, 0x06, 0x18, 0xa3, 0x1b, 0x08, 0x98, 0x23, 0x00, 0x85, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x04, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x0e, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x02, 0x01, 0x07, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x9a, 0x12, 0x18, 0x01, 0x28, 0x84, 0x62, 0x20, 0x2d, 0x40, 0x08, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x83, 0x0c, 0x6f, 0x0c, 0x24, 0xc6, 0x45, 0x66, 0x43, 0x10, 0x4c, 0x10, 0x86, 0x61, 0x82, 0x30, 0x10, 0x1b, 0x84, 0x81, 0x98, 0x20, 0x0c, 0xc5, 0x06, 0x61, 0x30, 0x28, 0xc0, 0xcd, 0x4d, 0x10, 0x06, 0x63, 0xc3, 0x80, 0x24, 0xc4, 0x04, 0x41, 0x00, 0x36, 0x00, 0x1b, 0x06, 0x82, 0x61, 0x36, 0x04, 0xcd, 0x86, 0x61, 0x58, 0x1c, 0x12, 0x6d, 0x61, 0x69, 0x6e, 0x13, 0x04, 0xe5, 0xd8, 0x20, 0x10, 0xd1, 0x86, 0x62, 0x81, 0x00, 0x40, 0xaa, 0xc2, 0xc6, 0x66, 0xd7, 0xe6, 0x92, 0x46, 0x56, 0xe6, 0x46, 0x37, 0x25, 0x08, 0xaa, 0x90, 0xe1, 0xb9, 0xd8, 0x95, 0xc9, 0xcd, 0xa5, 0xbd, 0xb9, 0x4d, 0x09, 0x88, 0x26, 0x64, 0x78, 0x2e, 0x76, 0x61, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x02, 0xa3, 0x0e, 0x19, 0x9e, 0xcb, 0x1c, 0x5a, 0x18, 0x59, 0x99, 0x5c, 0xd3, 0x1b, 0x59, 0x19, 0xdb, 0x94, 0x20, 0xa9, 0x44, 0x86, 0xe7, 0x42, 0x97, 0x07, 0x57, 0x16, 0xe4, 0xe6, 0xf6, 0x46, 0x17, 0x46, 0x97, 0xf6, 0xe6, 0x36, 0x37, 0x25, 0x70, 0xea, 0x90, 0xe1, 0xb9, 0x94, 0xb9, 0xd1, 0xc9, 0xe5, 0x41, 0xbd, 0xa5, 0xb9, 0xd1, 0xcd, 0x4d, 0x09, 0x24, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0x03, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x26, 0xd0, 0x0c, 0x97, 0xef, 0x3c, 0xfe, 0x80, 0x48, 0x02, 0x10, 0x0d, 0x06, 0x40, 0x30, 0x00, 0xd2, 0x58, 0xc0, 0x35, 0x5c, 0xbe, 0xf3, 0xf8, 0x48, 0xd3, 0x10, 0x11, 0xe7, 0x54, 0x44, 0x04, 0x18, 0x84, 0x8f, 0xdc, 0x36, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x13, 0x04, 0x43, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34, 0x85, 0x1b, 0x50, 0xa4, 0x01, 0x64, 0x35, 0x00, 0x00, 0x00, 0x00, 0x23, 0x06, 0x05, 0x00, 0x82, 0x60, 0x40, 0x28, 0xc3, 0x70, 0x43, 0x80, 0x80, 0xc1, 0x2c, 0x43, 0x20, 0x04, 0x23, 0x06, 0x06, 0x00, 0x82, 0x60, 0x70, 0x2c, 0xc4, 0x30, 0x4b, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, }; const D3D12_SHADER_BYTECODE ps_underestimate = { use_dxil ? (const void*)ps_underestimate_dxil : (const void*)ps_underestimate_dxbc, use_dxil ? sizeof(ps_underestimate_dxil) : sizeof(ps_underestimate_dxbc), }; static const D3D12_INPUT_ELEMENT_DESC layout_desc[] = { {"position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, }; static const struct vec4 vertices[] = { { 0.5f, -0.5f, 1.0f, 1.0f}, {-0.5f, -0.5f, 1.0f, 1.0f}, { 0.0f, 0.5f, 1.0f, 1.0f}, }; static const struct { unsigned int stencil_ref; D3D12_CONSERVATIVE_RASTERIZATION_TIER min_tier; } tests[] = { { 0x1, D3D12_CONSERVATIVE_RASTERIZATION_TIER_1 }, { 0x3, D3D12_CONSERVATIVE_RASTERIZATION_TIER_1 }, { 0x7, D3D12_CONSERVATIVE_RASTERIZATION_TIER_3 }, }; memset(&desc, 0, sizeof(desc)); desc.no_root_signature = true; if (!init_test_context(&context, &desc)) return; hr = ID3D12Device_CheckFeatureSupport(context.device, D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)); ok(hr == S_OK, "Failed to check feature support, hr %#x.\n", hr); if (!options.ConservativeRasterizationTier) { skip("Conservative rasterization not supported by device.\n"); destroy_test_context(&context); return; } heap_desc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION; heap_desc.Count = ARRAY_SIZE(tests); heap_desc.NodeMask = 0; hr = ID3D12Device_CreateQueryHeap(context.device, &heap_desc, &IID_ID3D12QueryHeap, (void **)&query_heap); ok(SUCCEEDED(hr), "Failed to create query heap, hr %#x.\n", hr); readback = create_readback_buffer(context.device, ARRAY_SIZE(tests) * sizeof(uint64_t)); root_signature_desc.NumParameters = 0; root_signature_desc.pParameters = NULL; root_signature_desc.NumStaticSamplers = 0; root_signature_desc.pStaticSamplers = NULL; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; hr = create_root_signature(context.device, &root_signature_desc, &root_signature); ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr); command_list = context.list; queue = context.queue; init_depth_stencil(&ds, context.device, 32, 32, 1, 1, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 0, NULL); vb = create_upload_buffer(context.device, sizeof(vertices), vertices); vbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(vb); vbv.StrideInBytes = sizeof(*vertices); vbv.SizeInBytes = sizeof(vertices); input_layout.pInputElementDescs = layout_desc; input_layout.NumElements = ARRAY_SIZE(layout_desc); init_pipeline_state_desc(&pso_desc, root_signature, DXGI_FORMAT_UNKNOWN, &vs, &ps, &input_layout); pso_desc.DSVFormat = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; pso_desc.DepthStencilState.DepthEnable = true; pso_desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; pso_desc.DepthStencilState.StencilEnable = true; pso_desc.DepthStencilState.StencilWriteMask = 0x01; pso_desc.DepthStencilState.FrontFace.StencilFailOp = D3D12_STENCIL_OP_REPLACE; pso_desc.DepthStencilState.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_REPLACE; pso_desc.DepthStencilState.FrontFace.StencilPassOp = D3D12_STENCIL_OP_REPLACE; pso_desc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; pso_desc.DepthStencilState.BackFace = pso_desc.DepthStencilState.FrontFace; pso_desc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON; hr = ID3D12Device_CreateGraphicsPipelineState(context.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pipeline_conservative_overestimate); ok(hr == S_OK, "Failed to create pipeline, hr %#x.\n", hr); pso_desc.DepthStencilState.StencilWriteMask = 0x02; pso_desc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; hr = ID3D12Device_CreateGraphicsPipelineState(context.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pipeline_conservative_off); ok(hr == S_OK, "Failed to create pipeline, hr %#x.\n", hr); if (options.ConservativeRasterizationTier >= D3D12_CONSERVATIVE_RASTERIZATION_TIER_3) { pso_desc.PS = ps_underestimate; pso_desc.DepthStencilState.StencilWriteMask = 0x04; pso_desc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON; hr = ID3D12Device_CreateGraphicsPipelineState(context.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pipeline_conservative_underestimate); ok(hr == S_OK, "Failed to create pipeline, hr %#x.\n", hr); } else pipeline_conservative_underestimate = NULL; init_pipeline_state_desc(&pso_desc, root_signature, DXGI_FORMAT_UNKNOWN, NULL, NULL, NULL); pso_desc.DSVFormat = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; pso_desc.DepthStencilState.DepthEnable = true; pso_desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; pso_desc.DepthStencilState.StencilEnable = true; pso_desc.DepthStencilState.StencilReadMask = 0xFF; pso_desc.DepthStencilState.StencilWriteMask = 0x00; pso_desc.DepthStencilState.FrontFace.StencilFailOp = D3D12_STENCIL_OP_KEEP; pso_desc.DepthStencilState.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_KEEP; pso_desc.DepthStencilState.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP; pso_desc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_EQUAL; pso_desc.DepthStencilState.BackFace = pso_desc.DepthStencilState.FrontFace; pso_desc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; hr = ID3D12Device_CreateGraphicsPipelineState(context.device, &pso_desc, &IID_ID3D12PipelineState, (void **)&pipeline_stencil_test); ok(hr == S_OK, "Failed to create pipeline, hr %#x.\n", hr); ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 0, NULL, false, &ds.dsv_handle); ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, ds.dsv_handle, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 0.0f, 0, 0, NULL); ID3D12GraphicsCommandList_OMSetStencilRef(command_list, 0xFF); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, &vbv); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); ID3D12GraphicsCommandList_SetPipelineState(command_list, pipeline_conservative_overestimate); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); ID3D12GraphicsCommandList_SetPipelineState(command_list, pipeline_conservative_off); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); if (pipeline_conservative_underestimate) { ID3D12GraphicsCommandList_SetPipelineState(command_list, pipeline_conservative_underestimate); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); } ID3D12GraphicsCommandList_SetPipelineState(command_list, pipeline_stencil_test); for (i = 0; i < ARRAY_SIZE(tests); i++) { ID3D12GraphicsCommandList_OMSetStencilRef(command_list, tests[i].stencil_ref); ID3D12GraphicsCommandList_BeginQuery(command_list, query_heap, D3D12_QUERY_TYPE_OCCLUSION, i); ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); ID3D12GraphicsCommandList_EndQuery(command_list, query_heap, D3D12_QUERY_TYPE_OCCLUSION, i); } ID3D12GraphicsCommandList_ResolveQueryData(command_list, query_heap, D3D12_QUERY_TYPE_OCCLUSION, 0, ARRAY_SIZE(tests), readback, 0); get_buffer_readback_with_command_list(readback, DXGI_FORMAT_UNKNOWN, &rb, queue, command_list); for (i = 0; i < ARRAY_SIZE(tests); i++) { vkd3d_test_set_context("Test %u", i); if (options.ConservativeRasterizationTier >= tests[i].min_tier) { value = get_readback_uint64(&rb, i, 0); ok(value, "Unexpected value %"PRIu64".\n", value); } else skip("Conservative rasterization tier %u not supported.\n", tests[i].min_tier); } ID3D12PipelineState_Release(pipeline_conservative_off); ID3D12PipelineState_Release(pipeline_conservative_overestimate); ID3D12PipelineState_Release(pipeline_stencil_test); if (pipeline_conservative_underestimate) ID3D12PipelineState_Release(pipeline_conservative_underestimate); release_resource_readback(&rb); ID3D12RootSignature_Release(root_signature); ID3D12QueryHeap_Release(query_heap); ID3D12Resource_Release(readback); ID3D12Resource_Release(vb); destroy_depth_stencil(&ds); destroy_test_context(&context); } void test_conservative_rasterization_dxbc(void) { test_conservative_rasterization(false); } void test_conservative_rasterization_dxil(void) { test_conservative_rasterization(true); }