From 4efa2266e6739e05381ed3904a128fa10fd313d4 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Thu, 4 Feb 2016 23:25:04 +0100 Subject: [PATCH] rsx/common/d3d12: Use m_texture_dirty[i] to signal texture state change and avoid unecessary bind operation. --- rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp | 19 +++++++++++++-- rpcs3/Emu/RSX/D3D12/D3D12GSRender.h | 5 +++- rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp | 33 ++++++++------------------- rpcs3/Emu/RSX/RSXThread.cpp | 2 ++ rpcs3/Emu/RSX/RSXThread.h | 1 + rpcs3/Emu/RSX/rsx_methods.cpp | 19 +++++++++++++++ 6 files changed, 53 insertions(+), 26 deletions(-) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 2121728680..d81b69ede9 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -303,9 +303,24 @@ void D3D12GSRender::end() get_current_resource_storage().command_list->SetPipelineState(std::get<0>(m_current_pso).Get()); std::chrono::time_point texture_duration_start = std::chrono::system_clock::now(); - if (std::get<2>(m_current_pso) > 0) + 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(), currentDescriptorIndex + 3 + vertex_buffer_count, std::get<2>(m_current_pso) > 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()) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 1a4f6d4a40..b290478bc6 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -127,6 +127,9 @@ private: // Used to fill unused texture slot ID3D12Resource *m_dummy_texture; + // Currently used shader resources / samplers descriptor + std::array, 16> m_current_shader_resources = {}; + std::array m_current_samplers = {}; public: D3D12GSRender(); virtual ~D3D12GSRender(); @@ -165,7 +168,7 @@ private: * Create necessary resource view/sampler descriptors in the per frame storage struct. * If the count of enabled texture is below texture_count, fills with dummy texture and sampler. */ - void upload_and_bind_textures(ID3D12GraphicsCommandList *command_list, size_t descriptor_index, size_t texture_count); + void upload_and_bind_textures(ID3D12GraphicsCommandList *command_list, size_t texture_count); /** * Creates render target if necessary. diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp index e24b3e1583..d5cf7caa24 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp @@ -171,12 +171,14 @@ D3D12_SHADER_RESOURCE_VIEW_DESC get_srv_descriptor_with_dimensions(const rsx::te } } -void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_list, size_t descriptor_index, size_t texture_count) +void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_list, size_t texture_count) { - size_t used_texture = 0; - - for (u32 i = 0; i < rsx::limits::textures_count; ++i) + for (u32 i = 0; i < 16; ++i) { + if (!m_textures_dirty[i]) + continue; + m_textures_dirty[i] = false; + if (!textures[i].enabled()) { // Now fill remaining texture slots with dummy texture/sampler @@ -190,21 +192,14 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_ D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0, D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0, D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0); - m_device->CreateShaderResourceView(m_dummy_texture, &shader_resource_view_desc, - CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart()) - .Offset((INT)descriptor_index + (INT)used_texture, m_descriptor_stride_srv_cbv_uav) - ); + m_current_shader_resources[i] = std::make_tuple(m_dummy_texture, shader_resource_view_desc); D3D12_SAMPLER_DESC sampler_desc = {}; sampler_desc.Filter = D3D12_FILTER_MIN_MAG_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(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetCPUDescriptorHandleForHeapStart()) - .Offset((INT)get_current_resource_storage().current_sampler_index + (INT)used_texture, m_descriptor_stride_samplers) - ); - used_texture++; + m_current_samplers[i] = sampler_desc; continue; } size_t w = textures[i].width(), h = textures[i].height(); @@ -357,9 +352,7 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_ break; } - m_device->CreateShaderResourceView(vram_texture, &shared_resource_view_desc, - CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart()) - .Offset((UINT)descriptor_index + (UINT)used_texture, m_descriptor_stride_srv_cbv_uav)); + m_current_shader_resources[i] = std::make_tuple(vram_texture, shared_resource_view_desc); if (get_current_resource_storage().current_sampler_index + 16 > 2048) { @@ -373,13 +366,7 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_ }; command_list->SetDescriptorHeaps(2, descriptors); } - m_device->CreateSampler(&get_sampler_desc(textures[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)used_texture, m_descriptor_stride_samplers)); - - used_texture++; + m_current_samplers[i] = get_sampler_desc(textures[i]); } - - } #endif diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 3d5698cc0f..b34e80173c 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -278,6 +278,8 @@ namespace rsx { return on_access_violation(address, is_writing); }; + m_rtts_dirty = true; + memset(m_textures_dirty, -1, sizeof(m_textures_dirty)); } thread::~thread() diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index f6cc2902fc..6904bbc07d 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -289,6 +289,7 @@ namespace rsx std::vector inline_vertex_array; bool m_rtts_dirty; + bool m_textures_dirty[16]; protected: std::array get_color_surface_addresses() const; u32 get_zeta_surface_address() const; diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index cd645fe8a6..cb7d42d845 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -287,6 +287,15 @@ namespace rsx { rsx->m_rtts_dirty = true; } + + template + struct set_texture_dirty_bit + { + force_inline static void impl(thread* rsx, u32 arg) + { + rsx->m_textures_dirty[index] = true; + } + }; } namespace nv308a @@ -834,6 +843,16 @@ namespace rsx bind(); bind(); bind(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); + bind_range(); //NV308A bind_range();