void GBuffer::Clear(ID3D12DescriptorHeap* dsvHeap) { // Set the viewport. _pCommandList->RSSetViewports(1, &Camera::Main()->GetViewPort()); // Indicate that the GBuffer textures will be used as render targets. for (int i = 0; i < GBUFFER_NUM_BUFFERS; ++i) { _pCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(_pTextures[i]->GetResource(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); } // Bind the render target view array and depth stencil buffer to the output render pipeline. CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle = CD3DX12_CPU_DESCRIPTOR_HANDLE( _pRtvHeap->GetCPUDescriptorHandleForHeapStart(), 0, D3DUtils::GetRTVDescriptorSize()); _pCommandList->OMSetRenderTargets(GBUFFER_NUM_BUFFERS, &rtvHandle, TRUE, &dsvHeap->GetCPUDescriptorHandleForHeapStart()); // Clear the render target buffers. FLOAT clearColour[] = { 0.0f, 0.0f, 0.0f, 1.0f }; _rtvHandle = CD3DX12_CPU_DESCRIPTOR_HANDLE(_pRtvHeap->GetCPUDescriptorHandleForHeapStart()); for (int i = 0; i < GBUFFER_NUM_BUFFERS; ++i) { _pCommandList->ClearRenderTargetView(_rtvHandle, clearColour, 0, nullptr); _rtvHandle.Offset(1, D3DUtils::GetRTVDescriptorSize()); } }
void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlist) { // Exit early if there is no rtt changes if (!m_rtts_dirty) return; m_rtts_dirty = false; std::array<float, 4> clear_color = { rsx::method_registers.clear_color_r() / 255.f, rsx::method_registers.clear_color_g() / 255.f, rsx::method_registers.clear_color_b() / 255.f, rsx::method_registers.clear_color_a() / 255.f, }; m_rtts.prepare_render_target(copycmdlist, rsx::method_registers.surface_color(), rsx::method_registers.surface_depth_fmt(), rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height(), rsx::method_registers.surface_color_target(), get_color_surface_addresses(), get_zeta_surface_address(), m_device.Get(), clear_color, 1.f, 0); // write descriptors DXGI_FORMAT dxgi_format = get_color_surface_format(rsx::method_registers.surface_color()); D3D12_RENDER_TARGET_VIEW_DESC rtt_view_desc = {}; rtt_view_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; rtt_view_desc.Format = dxgi_format; m_rtts.current_rtts_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart()) .Offset((INT)get_current_resource_storage().render_targets_descriptors_heap_index * m_descriptor_stride_rtv); size_t rtt_index = 0; for (u8 i : get_rtt_indexes(rsx::method_registers.surface_color_target())) { if (std::get<1>(m_rtts.m_bound_render_targets[i]) == nullptr) continue; m_device->CreateRenderTargetView(std::get<1>(m_rtts.m_bound_render_targets[i]), &rtt_view_desc, CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle).Offset((INT)rtt_index * m_descriptor_stride_rtv)); rtt_index++; } get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index; if (std::get<1>(m_rtts.m_bound_depth_stencil) == nullptr) return; m_rtts.current_ds_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart()) .Offset((INT)get_current_resource_storage().depth_stencil_descriptor_heap_index * m_descriptor_stride_dsv); get_current_resource_storage().depth_stencil_descriptor_heap_index += 1; D3D12_DEPTH_STENCIL_VIEW_DESC depth_stencil_view_desc = {}; depth_stencil_view_desc.Format = get_depth_stencil_surface_format(rsx::method_registers.surface_depth_fmt()); depth_stencil_view_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; m_device->CreateDepthStencilView(std::get<1>(m_rtts.m_bound_depth_stencil), &depth_stencil_view_desc, m_rtts.current_ds_handle); }
void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex) { size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(256); // Scale offset buffer // Separate constant buffer void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + 256)); fill_scale_offset_data(mapped_buffer); int is_alpha_tested = rsx::method_registers.alpha_test_enabled(); u8 alpha_ref_raw = rsx::method_registers.alpha_ref(); float alpha_ref = alpha_ref_raw / 255.f; memcpy((char*)mapped_buffer + 16 * sizeof(float), &is_alpha_tested, sizeof(int)); memcpy((char*)mapped_buffer + 17 * sizeof(float), &alpha_ref, sizeof(float)); f32 fogp0 = rsx::method_registers.fog_params_0(); f32 fogp1 = rsx::method_registers.fog_params_1(); memcpy((char*)mapped_buffer + 18 * sizeof(float), &fogp0, sizeof(float)); memcpy((char*)mapped_buffer + 19 * sizeof(float), &fogp1, sizeof(float)); m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + 256)); D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = { m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset, 256 }; m_device->CreateConstantBufferView(&constant_buffer_view_desc, CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart()) .Offset((INT)descriptorIndex, m_descriptor_stride_srv_cbv_uav)); }
D3D12_CPU_DESCRIPTOR_HANDLE D3D12Render::CurrentBackBufferView()const { return CD3DX12_CPU_DESCRIPTOR_HANDLE( m_pRendetTargetViewHeap->GetCPUDescriptorHandleForHeapStart(), m_CurrBackBuffer, m_RtvDescriptorSize); }
void D3D12GSRender::clear_surface(u32 arg) { // Ignore clear if surface target is set to CELL_GCM_SURFACE_TARGET_NONE if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return; std::chrono::time_point<std::chrono::system_clock> start_duration = std::chrono::system_clock::now(); std::chrono::time_point<std::chrono::system_clock> rtt_duration_start = std::chrono::system_clock::now(); prepare_render_targets(get_current_resource_storage().command_list.Get()); std::chrono::time_point<std::chrono::system_clock> rtt_duration_end = std::chrono::system_clock::now(); m_timers.prepare_rtt_duration += std::chrono::duration_cast<std::chrono::microseconds>(rtt_duration_end - rtt_duration_start).count(); if (arg & 0x1 || arg & 0x2) { get_current_resource_storage().depth_stencil_descriptor_heap_index++; if (arg & 0x1) { u32 clear_depth = rsx::method_registers.z_clear_value(); u32 max_depth_value = get_max_depth_value(rsx::method_registers.surface_depth_fmt()); get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_DEPTH, clear_depth / (float)max_depth_value, 0, 1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height())); } if (arg & 0x2) get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_STENCIL, 0.f, get_clear_stencil(rsx::method_registers.stencil_clear_value()), 1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height())); } if (arg & 0xF0) { CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle); size_t rtt_index = get_num_rtt(rsx::method_registers.surface_color_target()); get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index; std::array<float, 4> clear_color = { rsx::method_registers.clear_color_r() / 255.f, rsx::method_registers.clear_color_g() / 255.f, rsx::method_registers.clear_color_b() / 255.f, rsx::method_registers.clear_color_a() / 255.f, }; for (unsigned i = 0; i < rtt_index; i++) get_current_resource_storage().command_list->ClearRenderTargetView(handle.Offset(i, m_descriptor_stride_rtv), clear_color.data(), 1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height())); } std::chrono::time_point<std::chrono::system_clock> end_duration = std::chrono::system_clock::now(); m_timers.draw_calls_duration += std::chrono::duration_cast<std::chrono::microseconds>(end_duration - start_duration).count(); m_timers.draw_calls_count++; if (g_cfg_rsx_debug_output) { CHECK_HRESULT(get_current_resource_storage().command_list->Close()); m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf()); get_current_resource_storage().set_new_command_list(); } }
void ResourceManager::AddSampler(D3D12_SAMPLER_DESC* desc, D3D12_CPU_DESCRIPTOR_HANDLE& handleCPU) { if (m_indexFirstFreeSlotSampler >= m_numSamplers || m_indexFirstFreeSlotSampler < 0) { throw GFX_Exception("Error adding Sampler Heap. No space remaining."); } handleCPU = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_pheapSampler->GetCPUDescriptorHandleForHeapStart(), m_indexFirstFreeSlotSampler, m_sizeSamplerHeapDesc); m_pDev->CreateSampler(desc, handleCPU); ++m_indexFirstFreeSlotSampler; }
void GBuffer::CreateHeaps() { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = GBUFFER_NUM_BUFFERS; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; LOGFAILEDCOM(_pDevice->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&_pRtvHeap))); _rtvHandle = CD3DX12_CPU_DESCRIPTOR_HANDLE(_pRtvHeap->GetCPUDescriptorHandleForHeapStart()); }
void ResourceManager::AddDSV(ID3D12Resource* tex, D3D12_DEPTH_STENCIL_VIEW_DESC* desc, D3D12_CPU_DESCRIPTOR_HANDLE& handleCPU) { if (m_indexFirstFreeSlotDSV >= m_numDSVs || m_indexFirstFreeSlotDSV < 0) { throw GFX_Exception("Error adding to DSV Heap. No space remaining."); } handleCPU = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_pheapDSV->GetCPUDescriptorHandleForHeapStart(), m_indexFirstFreeSlotDSV, m_sizeDSVHeapDesc); m_pDev->CreateDSV(tex, desc, handleCPU); ++m_indexFirstFreeSlotDSV; }
void ResourceManager::AddRTV(ID3D12Resource* tex, D3D12_RENDER_TARGET_VIEW_DESC* desc, D3D12_CPU_DESCRIPTOR_HANDLE& handleCPU) { if (m_indexFirstFreeSlotRTV >= m_numRTVs || m_indexFirstFreeSlotRTV < 0) { throw GFX_Exception("Error adding to RTV Heap. No space remaining."); } handleCPU = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_pheapRTV->GetCPUDescriptorHandleForHeapStart(), m_indexFirstFreeSlotRTV, m_sizeRTVHeapDesc); m_pDev->CreateRTV(tex, desc, handleCPU); ++m_indexFirstFreeSlotRTV; }
void ResourceManager::AddSRV(ID3D12Resource* tex, D3D12_SHADER_RESOURCE_VIEW_DESC* desc, D3D12_CPU_DESCRIPTOR_HANDLE& handleCPU, D3D12_GPU_DESCRIPTOR_HANDLE& handleGPU) { if (m_indexFirstFreeSlotCBVSRVUAV >= m_numCBVSRVUAVs || m_indexFirstFreeSlotCBVSRVUAV < 0) { throw GFX_Exception("Error adding SRV to CBV/SRV/UAV Heap. No space remaining."); } handleCPU = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_pheapCBVSRVUAV->GetCPUDescriptorHandleForHeapStart(), m_indexFirstFreeSlotCBVSRVUAV, m_sizeCBVSRVUAVHeapDesc); handleGPU = CD3DX12_GPU_DESCRIPTOR_HANDLE(m_pheapCBVSRVUAV->GetGPUDescriptorHandleForHeapStart(), m_indexFirstFreeSlotCBVSRVUAV, m_sizeCBVSRVUAVHeapDesc); m_pDev->CreateSRV(tex, desc, handleCPU); ++m_indexFirstFreeSlotCBVSRVUAV; }
void D3D12GSRender::upload_and_bind_vertex_shader_constants(size_t descriptor_index) { size_t buffer_size = 512 * 4 * sizeof(float); size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size); void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size)); fill_vertex_program_constants_data(mapped_buffer); m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size)); D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = { m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset, (UINT)buffer_size }; m_device->CreateConstantBufferView(&constant_buffer_view_desc, CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart()) .Offset((INT)descriptor_index, m_descriptor_stride_srv_cbv_uav)); }
void D3D12GSRender::upload_and_bind_fragment_shader_constants(size_t descriptor_index) { // Get constant from fragment program size_t buffer_size = m_pso_cache.get_fragment_constants_buffer_size(m_fragment_program); // Multiple of 256 never 0 buffer_size = (buffer_size + 255) & ~255; size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size); size_t offset = 0; float *mapped_buffer = m_buffer_data.map<float>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size)); m_pso_cache.fill_fragment_constans_buffer({ mapped_buffer, gsl::narrow<int>(buffer_size) }, m_fragment_program); m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size)); D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = { m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset, (UINT)buffer_size }; m_device->CreateConstantBufferView(&constant_buffer_view_desc, CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart()) .Offset((INT)descriptor_index, m_descriptor_stride_srv_cbv_uav)); }
void D3D12GSRender::flip(int buffer) { ID3D12Resource *resource_to_flip; float viewport_w, viewport_h; if (!is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))) { resource_storage &storage = get_current_resource_storage(); assert(storage.ram_framebuffer == nullptr); size_t w = 0, h = 0, row_pitch = 0; size_t offset = 0; if (false) { CellGcmDisplayInfo* buffers = nullptr;// = vm::ps3::_ptr<CellGcmDisplayInfo>(m_gcm_buffers_addr); u32 addr = rsx::get_address(gcm_buffers[gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL); w = gcm_buffers[gcm_current_buffer].width; h = gcm_buffers[gcm_current_buffer].height; u8 *src_buffer = vm::ps3::_ptr<u8>(addr); row_pitch = align(w * 4, 256); size_t texture_size = row_pitch * h; // * 4 for mipmap levels size_t heap_offset = m_buffer_data.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(texture_size); void *mapped_buffer = m_buffer_data.map<void>(heap_offset); for (unsigned row = 0; row < h; row++) memcpy((char*)mapped_buffer + row * row_pitch, (char*)src_buffer + row * w * 4, w * 4); m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + texture_size)); offset = heap_offset; } CHECK_HRESULT( m_device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, (UINT)w, (UINT)h, 1, 1), D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(storage.ram_framebuffer.GetAddressOf()) ) ); get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(storage.ram_framebuffer.Get(), 0), 0, 0, 0, &CD3DX12_TEXTURE_COPY_LOCATION(m_buffer_data.get_heap(), { offset, { DXGI_FORMAT_R8G8B8A8_UNORM, (UINT)w, (UINT)h, 1, (UINT)row_pitch } }), nullptr); get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(storage.ram_framebuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ)); resource_to_flip = storage.ram_framebuffer.Get(); viewport_w = (float)w, viewport_h = (float)h; } else { if (std::get<1>(m_rtts.m_bound_render_targets[0]) != nullptr) { get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_render_targets[0]), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ)); resource_to_flip = std::get<1>(m_rtts.m_bound_render_targets[0]); } else if (std::get<1>(m_rtts.m_bound_render_targets[1]) != nullptr) { get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_render_targets[1]), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ)); resource_to_flip = std::get<1>(m_rtts.m_bound_render_targets[1]); } else resource_to_flip = nullptr; } get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); D3D12_VIEWPORT viewport = { 0.f, 0.f, (float)m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()]->GetDesc().Width, (float)m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()]->GetDesc().Height, 0.f, 1.f }; get_current_resource_storage().command_list->RSSetViewports(1, &viewport); D3D12_RECT box = { 0, 0, (LONG)m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()]->GetDesc().Width, (LONG)m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()]->GetDesc().Height, }; get_current_resource_storage().command_list->RSSetScissorRects(1, &box); get_current_resource_storage().command_list->SetGraphicsRootSignature(m_output_scaling_pass.root_signature); get_current_resource_storage().command_list->SetPipelineState(m_output_scaling_pass.pso); D3D12_SHADER_RESOURCE_VIEW_DESC shader_resource_view_desc = {}; // FIXME: Not always true shader_resource_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; shader_resource_view_desc.Texture2D.MipLevels = 1; if (is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))) shader_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; else shader_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING( D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3, D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0 ); m_device->CreateShaderResourceView(resource_to_flip, &shader_resource_view_desc, CD3DX12_CPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.texture_descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_srv_cbv_uav)); D3D12_SAMPLER_DESC sampler_desc = {}; sampler_desc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; m_device->CreateSampler(&sampler_desc, CD3DX12_CPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.sampler_descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_samplers)); ID3D12DescriptorHeap *descriptors_heaps[] = { m_output_scaling_pass.texture_descriptor_heap, m_output_scaling_pass.sampler_descriptor_heap }; get_current_resource_storage().command_list->SetDescriptorHeaps(2, descriptors_heaps); get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(0, CD3DX12_GPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.texture_descriptor_heap->GetGPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_srv_cbv_uav)); get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(1, CD3DX12_GPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.sampler_descriptor_heap->GetGPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_samplers)); get_current_resource_storage().command_list->OMSetRenderTargets(1, &CD3DX12_CPU_DESCRIPTOR_HANDLE(m_backbuffer_descriptor_heap[m_swap_chain->GetCurrentBackBufferIndex()]->GetCPUDescriptorHandleForHeapStart()), true, nullptr); D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view = {}; vertex_buffer_view.BufferLocation = m_output_scaling_pass.vertex_buffer->GetGPUVirtualAddress(); vertex_buffer_view.StrideInBytes = 4 * sizeof(float); vertex_buffer_view.SizeInBytes = 16 * sizeof(float); get_current_resource_storage().command_list->IASetVertexBuffers(0, 1, &vertex_buffer_view); get_current_resource_storage().command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); if (resource_to_flip) get_current_resource_storage().command_list->DrawInstanced(4, 1, 0, 0); if (!rpcs3::config.rsx.d3d12.overlay.value()) get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); if (is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) && resource_to_flip != nullptr) get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(resource_to_flip, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET)); CHECK_HRESULT(get_current_resource_storage().command_list->Close()); m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf()); if(rpcs3::config.rsx.d3d12.overlay.value()) render_overlay(); reset_timer(); std::chrono::time_point<std::chrono::system_clock> flip_start = std::chrono::system_clock::now(); CHECK_HRESULT(m_swap_chain->Present(rpcs3::state.config.rsx.vsync.value() ? 1 : 0, 0)); // Add an event signaling queue completion resource_storage &storage = get_non_current_resource_storage(); m_command_queue->Signal(storage.frame_finished_fence.Get(), storage.fence_value); storage.frame_finished_fence->SetEventOnCompletion(storage.fence_value, storage.frame_finished_handle); storage.fence_value++; storage.in_use = true; storage.dirty_textures.merge(m_rtts.invalidated_resources); m_rtts.invalidated_resources.clear(); // Get the put pos - 1. This way after cleaning we can set the get ptr to // this value, allowing heap to proceed even if we cleant before allocating // a new value (that's the reason of the -1) storage.buffer_heap_get_pos = m_buffer_data.get_current_put_pos_minus_one(); storage.readback_heap_get_pos = m_readback_resources.get_current_put_pos_minus_one(); // Now get ready for next frame resource_storage &new_storage = get_current_resource_storage(); new_storage.wait_and_clean(); if (new_storage.in_use) { m_buffer_data.m_get_pos = new_storage.buffer_heap_get_pos; m_readback_resources.m_get_pos = new_storage.readback_heap_get_pos; } m_frame->flip(nullptr); std::chrono::time_point<std::chrono::system_clock> flip_end = std::chrono::system_clock::now(); m_timers.flip_duration += std::chrono::duration_cast<std::chrono::microseconds>(flip_end - flip_start).count(); }
void D3D12GSRender::end() { std::chrono::time_point<std::chrono::system_clock> start_duration = std::chrono::system_clock::now(); std::chrono::time_point<std::chrono::system_clock> rtt_duration_start = std::chrono::system_clock::now(); prepare_render_targets(get_current_resource_storage().command_list.Get()); std::chrono::time_point<std::chrono::system_clock> rtt_duration_end = std::chrono::system_clock::now(); m_timers.prepare_rtt_duration += std::chrono::duration_cast<std::chrono::microseconds>(rtt_duration_end - rtt_duration_start).count(); std::chrono::time_point<std::chrono::system_clock> vertex_index_duration_start = std::chrono::system_clock::now(); size_t currentDescriptorIndex = get_current_resource_storage().descriptors_heap_index; size_t vertex_count; bool indexed_draw; std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> vertex_buffer_views; std::tie(indexed_draw, vertex_count, vertex_buffer_views) = upload_and_set_vertex_index_data(get_current_resource_storage().command_list.Get()); size_t vertex_buffer_count = vertex_buffer_views.size(); std::chrono::time_point<std::chrono::system_clock> vertex_index_duration_end = std::chrono::system_clock::now(); m_timers.vertex_index_duration += std::chrono::duration_cast<std::chrono::microseconds>(vertex_index_duration_end - vertex_index_duration_start).count(); std::chrono::time_point<std::chrono::system_clock> program_load_start = std::chrono::system_clock::now(); load_program(); std::chrono::time_point<std::chrono::system_clock> program_load_end = std::chrono::system_clock::now(); m_timers.program_load_duration += std::chrono::duration_cast<std::chrono::microseconds>(program_load_end - program_load_start).count(); get_current_resource_storage().command_list->SetGraphicsRootSignature(m_root_signatures[std::get<2>(m_current_pso)][vertex_buffer_count].Get()); get_current_resource_storage().command_list->OMSetStencilRef(rsx::method_registers[NV4097_SET_STENCIL_FUNC_REF]); std::chrono::time_point<std::chrono::system_clock> constants_duration_start = std::chrono::system_clock::now(); INT offset = 0; for (const auto view : vertex_buffer_views) { m_device->CreateShaderResourceView(m_vertex_buffer_data.Get(), &view, CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart()) .Offset((INT)currentDescriptorIndex + offset++, m_descriptor_stride_srv_cbv_uav)); } // Constants upload_and_bind_scale_offset_matrix(currentDescriptorIndex + vertex_buffer_count); upload_and_bind_vertex_shader_constants(currentDescriptorIndex + 1 + vertex_buffer_count); upload_and_bind_fragment_shader_constants(currentDescriptorIndex + 2 + vertex_buffer_count); std::chrono::time_point<std::chrono::system_clock> constants_duration_end = std::chrono::system_clock::now(); m_timers.constants_duration += std::chrono::duration_cast<std::chrono::microseconds>(constants_duration_end - constants_duration_start).count(); get_current_resource_storage().command_list->SetPipelineState(std::get<0>(m_current_pso).Get()); std::chrono::time_point<std::chrono::system_clock> texture_duration_start = std::chrono::system_clock::now(); size_t texture_count = std::get<2>(m_current_pso); if (texture_count > 0) { upload_and_bind_textures(get_current_resource_storage().command_list.Get(), texture_count); for (unsigned i = 0; i < texture_count; i++) { ID3D12Resource *tex_resource; D3D12_SHADER_RESOURCE_VIEW_DESC srv; std::tie(tex_resource, srv) = m_current_shader_resources[i]; m_device->CreateShaderResourceView(tex_resource, &srv, CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart()) .Offset((INT)currentDescriptorIndex + 3 + (INT)vertex_buffer_count + (INT)i, m_descriptor_stride_srv_cbv_uav) ); m_device->CreateSampler(&m_current_samplers[i], CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetCPUDescriptorHandleForHeapStart()) .Offset((UINT)get_current_resource_storage().current_sampler_index + (UINT)i, m_descriptor_stride_samplers)); } get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(0, CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart()) .Offset((INT)currentDescriptorIndex, m_descriptor_stride_srv_cbv_uav) ); get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(1, CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetGPUDescriptorHandleForHeapStart()) .Offset((INT)get_current_resource_storage().current_sampler_index, m_descriptor_stride_samplers) ); get_current_resource_storage().current_sampler_index += std::get<2>(m_current_pso); get_current_resource_storage().descriptors_heap_index += std::get<2>(m_current_pso) + 3 + vertex_buffer_count; } else { get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(0, CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart()) .Offset((INT)currentDescriptorIndex, m_descriptor_stride_srv_cbv_uav) ); get_current_resource_storage().descriptors_heap_index += 3 + vertex_buffer_count; } std::chrono::time_point<std::chrono::system_clock> texture_duration_end = std::chrono::system_clock::now(); m_timers.texture_duration += std::chrono::duration_cast<std::chrono::microseconds>(texture_duration_end - texture_duration_start).count(); set_rtt_and_ds(get_current_resource_storage().command_list.Get()); int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16; int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16; D3D12_VIEWPORT viewport = { 0.f, 0.f, (float)clip_w, (float)clip_h, (f32&)rsx::method_registers[NV4097_SET_CLIP_MIN], (f32&)rsx::method_registers[NV4097_SET_CLIP_MAX] }; get_current_resource_storage().command_list->RSSetViewports(1, &viewport); get_current_resource_storage().command_list->RSSetScissorRects(1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL])); get_current_resource_storage().command_list->IASetPrimitiveTopology(get_primitive_topology(draw_mode)); if (indexed_draw) get_current_resource_storage().command_list->DrawIndexedInstanced((UINT)vertex_count, 1, 0, 0, 0); else get_current_resource_storage().command_list->DrawInstanced((UINT)vertex_count, 1, 0, 0); std::chrono::time_point<std::chrono::system_clock> end_duration = std::chrono::system_clock::now(); m_timers.draw_calls_duration += std::chrono::duration_cast<std::chrono::microseconds>(end_duration - start_duration).count(); m_timers.draw_calls_count++; if (rpcs3::config.rsx.d3d12.debug_output.value()) { CHECK_HRESULT(get_current_resource_storage().command_list->Close()); m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf()); get_current_resource_storage().set_new_command_list(); } thread::end(); }
void D3D12GSRender::end() { std::chrono::time_point<steady_clock> start_duration = steady_clock::now(); std::chrono::time_point<steady_clock> rtt_duration_start = steady_clock::now(); prepare_render_targets(get_current_resource_storage().command_list.Get()); std::chrono::time_point<steady_clock> rtt_duration_end = steady_clock::now(); m_timers.prepare_rtt_duration += std::chrono::duration_cast<std::chrono::microseconds>(rtt_duration_end - rtt_duration_start).count(); std::chrono::time_point<steady_clock> vertex_index_duration_start = steady_clock::now(); size_t currentDescriptorIndex = get_current_resource_storage().descriptors_heap_index; size_t vertex_count; bool indexed_draw; std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> vertex_buffer_views; std::tie(indexed_draw, vertex_count, vertex_buffer_views) = upload_and_set_vertex_index_data(get_current_resource_storage().command_list.Get()); UINT vertex_buffer_count = static_cast<UINT>(vertex_buffer_views.size()); std::chrono::time_point<steady_clock> vertex_index_duration_end = steady_clock::now(); m_timers.vertex_index_duration += std::chrono::duration_cast<std::chrono::microseconds>(vertex_index_duration_end - vertex_index_duration_start).count(); std::chrono::time_point<steady_clock> program_load_start = steady_clock::now(); load_program(); std::chrono::time_point<steady_clock> program_load_end = steady_clock::now(); m_timers.program_load_duration += std::chrono::duration_cast<std::chrono::microseconds>(program_load_end - program_load_start).count(); get_current_resource_storage().command_list->SetGraphicsRootSignature(m_shared_root_signature.Get()); get_current_resource_storage().command_list->OMSetStencilRef(rsx::method_registers.stencil_func_ref()); std::chrono::time_point<steady_clock> constants_duration_start = steady_clock::now(); INT offset = 0; for (const auto view : vertex_buffer_views) { m_device->CreateShaderResourceView(m_vertex_buffer_data.Get(), &view, CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart()) .Offset((INT)currentDescriptorIndex + offset++, m_descriptor_stride_srv_cbv_uav)); } // Bind vertex buffer get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(VERTEX_BUFFERS_SLOT, CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart()) .Offset((INT)currentDescriptorIndex, m_descriptor_stride_srv_cbv_uav) ); // Constants const D3D12_CONSTANT_BUFFER_VIEW_DESC &fragment_constant_view = upload_fragment_shader_constants(); get_current_resource_storage().command_list->SetGraphicsRootConstantBufferView(FRAGMENT_CONSTANT_BUFFERS_SLOT, fragment_constant_view.BufferLocation); upload_and_bind_scale_offset_matrix(currentDescriptorIndex + vertex_buffer_count); get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(SCALE_OFFSET_SLOT, CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart()) .Offset((INT)currentDescriptorIndex + vertex_buffer_count, m_descriptor_stride_srv_cbv_uav) ); if (m_transform_constants_dirty && !g_cfg.video.debug_output) { m_current_transform_constants_buffer_descriptor_id = (u32)currentDescriptorIndex + 1 + vertex_buffer_count; upload_and_bind_vertex_shader_constants(currentDescriptorIndex + 1 + vertex_buffer_count); m_transform_constants_dirty = false; get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(VERTEX_CONSTANT_BUFFERS_SLOT, CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart()) .Offset(m_current_transform_constants_buffer_descriptor_id, m_descriptor_stride_srv_cbv_uav) ); } std::chrono::time_point<steady_clock> constants_duration_end = steady_clock::now(); m_timers.constants_duration += std::chrono::duration_cast<std::chrono::microseconds>(constants_duration_end - constants_duration_start).count(); get_current_resource_storage().command_list->SetPipelineState(std::get<0>(m_current_pso).Get()); std::chrono::time_point<steady_clock> texture_duration_start = steady_clock::now(); get_current_resource_storage().descriptors_heap_index += 2 + vertex_buffer_count; size_t texture_count = std::get<2>(m_current_pso); if (texture_count > 0) { if (get_current_resource_storage().current_sampler_index + 16 > 2048) { get_current_resource_storage().sampler_descriptors_heap_index = 1; get_current_resource_storage().current_sampler_index = 0; ID3D12DescriptorHeap *descriptors[] = { get_current_resource_storage().descriptors_heap.Get(), get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index].Get(), }; get_current_resource_storage().command_list->SetDescriptorHeaps(2, descriptors); } upload_textures(get_current_resource_storage().command_list.Get(), texture_count); m_device->CopyDescriptorsSimple(16, CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart()) .Offset((UINT)get_current_resource_storage().descriptors_heap_index, m_descriptor_stride_srv_cbv_uav), CD3DX12_CPU_DESCRIPTOR_HANDLE(m_current_texture_descriptors->GetCPUDescriptorHandleForHeapStart()), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ); m_device->CopyDescriptorsSimple(16, CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetCPUDescriptorHandleForHeapStart()) .Offset((UINT)get_current_resource_storage().current_sampler_index, m_descriptor_stride_samplers), CD3DX12_CPU_DESCRIPTOR_HANDLE(m_current_sampler_descriptors->GetCPUDescriptorHandleForHeapStart()), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER ); get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(TEXTURES_SLOT, CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart()) .Offset((INT)get_current_resource_storage().descriptors_heap_index, m_descriptor_stride_srv_cbv_uav) ); get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(SAMPLERS_SLOT, CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetGPUDescriptorHandleForHeapStart()) .Offset((INT)get_current_resource_storage().current_sampler_index, m_descriptor_stride_samplers) ); get_current_resource_storage().current_sampler_index += texture_count; get_current_resource_storage().descriptors_heap_index += texture_count; } std::chrono::time_point<steady_clock> texture_duration_end = steady_clock::now(); m_timers.texture_duration += std::chrono::duration_cast<std::chrono::microseconds>(texture_duration_end - texture_duration_start).count(); set_rtt_and_ds(get_current_resource_storage().command_list.Get()); int clip_w = rsx::method_registers.surface_clip_width(); int clip_h = rsx::method_registers.surface_clip_height(); D3D12_VIEWPORT viewport = { 0.f, 0.f, (float)clip_w, (float)clip_h, rsx::method_registers.clip_min(), rsx::method_registers.clip_max(), }; get_current_resource_storage().command_list->RSSetViewports(1, &viewport); get_current_resource_storage().command_list->RSSetScissorRects(1, &get_scissor(rsx::method_registers.scissor_origin_x(), rsx::method_registers.scissor_origin_y(), rsx::method_registers.scissor_width(), rsx::method_registers.scissor_height())); get_current_resource_storage().command_list->IASetPrimitiveTopology(get_primitive_topology(rsx::method_registers.current_draw_clause.primitive)); if (indexed_draw) get_current_resource_storage().command_list->DrawIndexedInstanced((UINT)vertex_count, 1, 0, 0, 0); else get_current_resource_storage().command_list->DrawInstanced((UINT)vertex_count, 1, 0, 0); std::chrono::time_point<steady_clock> end_duration = steady_clock::now(); m_timers.draw_calls_duration += std::chrono::duration_cast<std::chrono::microseconds>(end_duration - start_duration).count(); m_timers.draw_calls_count++; if (g_cfg.video.debug_output) { CHECK_HRESULT(get_current_resource_storage().command_list->Close()); m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf()); get_current_resource_storage().set_new_command_list(); } thread::end(); }
CD3DX12_CPU_DESCRIPTOR_HANDLE Renderer::GetRTVCPUHandle() { return CD3DX12_CPU_DESCRIPTOR_HANDLE(RTVHeap->GetCPUDescriptorHandleForHeapStart(), BufferFrameIndex, RTVDescSize); }