[D3D12] Don't create SRVs if textures not changed
This commit is contained in:
parent
b77ffe3df6
commit
131525e44d
|
@ -1166,9 +1166,11 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the textures - this may bind pipelines.
|
// Update the textures - this may bind pipelines.
|
||||||
|
uint64_t new_texture_bindings_hash_vertex, new_texture_bindings_hash_pixel;
|
||||||
texture_cache_->RequestTextures(
|
texture_cache_->RequestTextures(
|
||||||
vertex_shader->GetUsedTextureMask(),
|
vertex_shader->GetUsedTextureMask(),
|
||||||
pixel_shader != nullptr ? pixel_shader->GetUsedTextureMask() : 0);
|
pixel_shader != nullptr ? pixel_shader->GetUsedTextureMask() : 0,
|
||||||
|
new_texture_bindings_hash_vertex, new_texture_bindings_hash_pixel);
|
||||||
|
|
||||||
// Update viewport, scissor, blend factor and stencil reference.
|
// Update viewport, scissor, blend factor and stencil reference.
|
||||||
UpdateFixedFunctionState(command_list);
|
UpdateFixedFunctionState(command_list);
|
||||||
|
@ -1185,8 +1187,9 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||||
pipeline_render_targets);
|
pipeline_render_targets);
|
||||||
|
|
||||||
// Update constant buffers, descriptors and root parameters.
|
// Update constant buffers, descriptors and root parameters.
|
||||||
if (!UpdateBindings(command_list, vertex_shader, pixel_shader,
|
if (!UpdateBindings(command_list, vertex_shader, pixel_shader, root_signature,
|
||||||
root_signature)) {
|
new_texture_bindings_hash_vertex,
|
||||||
|
new_texture_bindings_hash_pixel)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1335,6 +1338,8 @@ bool D3D12CommandProcessor::BeginFrame() {
|
||||||
cbuffer_bindings_fetch_.up_to_date = false;
|
cbuffer_bindings_fetch_.up_to_date = false;
|
||||||
draw_view_full_update_ = 0;
|
draw_view_full_update_ = 0;
|
||||||
draw_sampler_full_update_ = 0;
|
draw_sampler_full_update_ = 0;
|
||||||
|
texture_bindings_hash_vertex_ = texture_bindings_hash_pixel_ =
|
||||||
|
texture_cache_->GetEmptyTextureBindingsHash();
|
||||||
primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||||
|
|
||||||
command_lists_[current_queue_frame_]->BeginRecording();
|
command_lists_[current_queue_frame_]->BeginRecording();
|
||||||
|
@ -1797,7 +1802,9 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
|
||||||
|
|
||||||
bool D3D12CommandProcessor::UpdateBindings(
|
bool D3D12CommandProcessor::UpdateBindings(
|
||||||
ID3D12GraphicsCommandList* command_list, const D3D12Shader* vertex_shader,
|
ID3D12GraphicsCommandList* command_list, const D3D12Shader* vertex_shader,
|
||||||
const D3D12Shader* pixel_shader, ID3D12RootSignature* root_signature) {
|
const D3D12Shader* pixel_shader, ID3D12RootSignature* root_signature,
|
||||||
|
uint64_t new_texture_bindings_hash_vertex,
|
||||||
|
uint64_t new_texture_bindings_hash_pixel) {
|
||||||
auto provider = GetD3D12Context()->GetD3D12Provider();
|
auto provider = GetD3D12Context()->GetD3D12Provider();
|
||||||
auto device = provider->GetDevice();
|
auto device = provider->GetDevice();
|
||||||
auto& regs = *register_file_;
|
auto& regs = *register_file_;
|
||||||
|
@ -1834,7 +1841,6 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
vertex_shader->GetTextureSRVs(vertex_texture_count);
|
vertex_shader->GetTextureSRVs(vertex_texture_count);
|
||||||
const D3D12Shader::SamplerBinding* vertex_samplers =
|
const D3D12Shader::SamplerBinding* vertex_samplers =
|
||||||
vertex_shader->GetSamplerBindings(vertex_sampler_count);
|
vertex_shader->GetSamplerBindings(vertex_sampler_count);
|
||||||
uint32_t texture_count = pixel_texture_count + vertex_texture_count;
|
|
||||||
uint32_t sampler_count = pixel_sampler_count + vertex_sampler_count;
|
uint32_t sampler_count = pixel_sampler_count + vertex_sampler_count;
|
||||||
|
|
||||||
// Begin updating descriptors.
|
// Begin updating descriptors.
|
||||||
|
@ -1843,9 +1849,14 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
bool write_pixel_float_constant_view = false;
|
bool write_pixel_float_constant_view = false;
|
||||||
bool write_bool_loop_constant_view = false;
|
bool write_bool_loop_constant_view = false;
|
||||||
bool write_fetch_constant_view = false;
|
bool write_fetch_constant_view = false;
|
||||||
// TODO(Triang3l): Update textures and samplers only if shaders or binding
|
// TODO(Triang3l): Update samplers only if shaders or binding
|
||||||
// hash change.
|
// hash change.
|
||||||
bool write_textures = texture_count != 0;
|
bool write_vertex_textures =
|
||||||
|
vertex_texture_count != 0 &&
|
||||||
|
(texture_bindings_hash_vertex_ != new_texture_bindings_hash_vertex);
|
||||||
|
bool write_pixel_textures =
|
||||||
|
pixel_texture_count != 0 &&
|
||||||
|
(texture_bindings_hash_pixel_ != new_texture_bindings_hash_pixel);
|
||||||
bool write_samplers = sampler_count != 0;
|
bool write_samplers = sampler_count != 0;
|
||||||
|
|
||||||
// Check if the float constant layout is still the same and get the counts.
|
// Check if the float constant layout is still the same and get the counts.
|
||||||
|
@ -2016,11 +2027,15 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
if (write_fetch_constant_view) {
|
if (write_fetch_constant_view) {
|
||||||
++view_count_partial_update;
|
++view_count_partial_update;
|
||||||
}
|
}
|
||||||
if (write_textures) {
|
if (write_vertex_textures) {
|
||||||
view_count_partial_update += texture_count;
|
view_count_partial_update += vertex_texture_count;
|
||||||
|
}
|
||||||
|
if (write_pixel_textures) {
|
||||||
|
view_count_partial_update += pixel_texture_count;
|
||||||
}
|
}
|
||||||
// All the constants + shared memory + textures.
|
// All the constants + shared memory + textures.
|
||||||
uint32_t view_count_full_update = 6 + texture_count;
|
uint32_t view_count_full_update =
|
||||||
|
6 + vertex_texture_count + pixel_texture_count;
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE view_cpu_handle;
|
D3D12_CPU_DESCRIPTOR_HANDLE view_cpu_handle;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE view_gpu_handle;
|
D3D12_GPU_DESCRIPTOR_HANDLE view_gpu_handle;
|
||||||
uint32_t descriptor_size_view = provider->GetViewDescriptorSize();
|
uint32_t descriptor_size_view = provider->GetViewDescriptorSize();
|
||||||
|
@ -2046,13 +2061,13 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
}
|
}
|
||||||
if (draw_view_full_update_ != view_full_update_index) {
|
if (draw_view_full_update_ != view_full_update_index) {
|
||||||
// Need to update all view descriptors.
|
// Need to update all view descriptors.
|
||||||
draw_view_full_update_ = view_full_update_index;
|
|
||||||
write_system_constant_view = true;
|
write_system_constant_view = true;
|
||||||
write_fetch_constant_view = true;
|
write_fetch_constant_view = true;
|
||||||
write_vertex_float_constant_view = true;
|
write_vertex_float_constant_view = true;
|
||||||
write_pixel_float_constant_view = true;
|
write_pixel_float_constant_view = true;
|
||||||
write_bool_loop_constant_view = true;
|
write_bool_loop_constant_view = true;
|
||||||
write_textures = texture_count != 0;
|
write_vertex_textures = vertex_texture_count != 0;
|
||||||
|
write_pixel_textures = pixel_texture_count != 0;
|
||||||
// If updating fully, write the shared memory descriptor (t0).
|
// If updating fully, write the shared memory descriptor (t0).
|
||||||
shared_memory_->CreateSRV(view_cpu_handle);
|
shared_memory_->CreateSRV(view_cpu_handle);
|
||||||
gpu_handle_shared_memory_ = view_gpu_handle;
|
gpu_handle_shared_memory_ = view_gpu_handle;
|
||||||
|
@ -2062,7 +2077,6 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
}
|
}
|
||||||
if (sampler_count != 0 &&
|
if (sampler_count != 0 &&
|
||||||
draw_sampler_full_update_ != sampler_full_update_index) {
|
draw_sampler_full_update_ != sampler_full_update_index) {
|
||||||
draw_sampler_full_update_ = sampler_full_update_index;
|
|
||||||
write_samplers = true;
|
write_samplers = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2128,35 +2142,35 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
view_gpu_handle.ptr += descriptor_size_view;
|
view_gpu_handle.ptr += descriptor_size_view;
|
||||||
current_graphics_root_up_to_date_ &= ~(1u << kRootParameter_FetchConstants);
|
current_graphics_root_up_to_date_ &= ~(1u << kRootParameter_FetchConstants);
|
||||||
}
|
}
|
||||||
if (write_textures) {
|
if (write_pixel_textures) {
|
||||||
if (pixel_texture_count != 0) {
|
assert_true(current_graphics_root_extras_.pixel_textures !=
|
||||||
assert_true(current_graphics_root_extras_.pixel_textures !=
|
RootExtraParameterIndices::kUnavailable);
|
||||||
RootExtraParameterIndices::kUnavailable);
|
gpu_handle_pixel_textures_ = view_gpu_handle;
|
||||||
gpu_handle_pixel_textures_ = view_gpu_handle;
|
for (uint32_t i = 0; i < pixel_texture_count; ++i) {
|
||||||
for (uint32_t i = 0; i < pixel_texture_count; ++i) {
|
const D3D12Shader::TextureSRV& srv = pixel_textures[i];
|
||||||
const D3D12Shader::TextureSRV& srv = pixel_textures[i];
|
texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension,
|
||||||
texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension,
|
view_cpu_handle);
|
||||||
view_cpu_handle);
|
view_cpu_handle.ptr += descriptor_size_view;
|
||||||
view_cpu_handle.ptr += descriptor_size_view;
|
view_gpu_handle.ptr += descriptor_size_view;
|
||||||
view_gpu_handle.ptr += descriptor_size_view;
|
|
||||||
}
|
|
||||||
current_graphics_root_up_to_date_ &=
|
|
||||||
~(1u << current_graphics_root_extras_.pixel_textures);
|
|
||||||
}
|
}
|
||||||
if (vertex_texture_count != 0) {
|
texture_bindings_hash_pixel_ = new_texture_bindings_hash_pixel;
|
||||||
assert_true(current_graphics_root_extras_.vertex_textures !=
|
current_graphics_root_up_to_date_ &=
|
||||||
RootExtraParameterIndices::kUnavailable);
|
~(1u << current_graphics_root_extras_.pixel_textures);
|
||||||
gpu_handle_vertex_textures_ = view_gpu_handle;
|
}
|
||||||
for (uint32_t i = 0; i < vertex_texture_count; ++i) {
|
if (write_vertex_textures) {
|
||||||
const D3D12Shader::TextureSRV& srv = vertex_textures[i];
|
assert_true(current_graphics_root_extras_.vertex_textures !=
|
||||||
texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension,
|
RootExtraParameterIndices::kUnavailable);
|
||||||
view_cpu_handle);
|
gpu_handle_vertex_textures_ = view_gpu_handle;
|
||||||
view_cpu_handle.ptr += descriptor_size_view;
|
for (uint32_t i = 0; i < vertex_texture_count; ++i) {
|
||||||
view_gpu_handle.ptr += descriptor_size_view;
|
const D3D12Shader::TextureSRV& srv = vertex_textures[i];
|
||||||
}
|
texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension,
|
||||||
current_graphics_root_up_to_date_ &=
|
view_cpu_handle);
|
||||||
~(1u << current_graphics_root_extras_.vertex_textures);
|
view_cpu_handle.ptr += descriptor_size_view;
|
||||||
|
view_gpu_handle.ptr += descriptor_size_view;
|
||||||
}
|
}
|
||||||
|
texture_bindings_hash_vertex_ = new_texture_bindings_hash_vertex;
|
||||||
|
current_graphics_root_up_to_date_ &=
|
||||||
|
~(1u << current_graphics_root_extras_.vertex_textures);
|
||||||
}
|
}
|
||||||
if (write_samplers) {
|
if (write_samplers) {
|
||||||
if (pixel_sampler_count != 0) {
|
if (pixel_sampler_count != 0) {
|
||||||
|
@ -2191,6 +2205,10 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrote new descriptors on the current page.
|
||||||
|
draw_view_full_update_ = view_full_update_index;
|
||||||
|
draw_sampler_full_update_ = sampler_full_update_index;
|
||||||
|
|
||||||
// Update the root parameters.
|
// Update the root parameters.
|
||||||
if (!(current_graphics_root_up_to_date_ &
|
if (!(current_graphics_root_up_to_date_ &
|
||||||
(1u << kRootParameter_FetchConstants))) {
|
(1u << kRootParameter_FetchConstants))) {
|
||||||
|
|
|
@ -193,7 +193,9 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||||
bool UpdateBindings(ID3D12GraphicsCommandList* command_list,
|
bool UpdateBindings(ID3D12GraphicsCommandList* command_list,
|
||||||
const D3D12Shader* vertex_shader,
|
const D3D12Shader* vertex_shader,
|
||||||
const D3D12Shader* pixel_shader,
|
const D3D12Shader* pixel_shader,
|
||||||
ID3D12RootSignature* root_signature);
|
ID3D12RootSignature* root_signature,
|
||||||
|
uint64_t new_texture_bindings_hash_vertex,
|
||||||
|
uint64_t new_texture_bindings_hash_pixel);
|
||||||
|
|
||||||
bool cache_clear_requested_ = false;
|
bool cache_clear_requested_ = false;
|
||||||
|
|
||||||
|
@ -301,6 +303,10 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||||
uint64_t draw_view_full_update_;
|
uint64_t draw_view_full_update_;
|
||||||
uint64_t draw_sampler_full_update_;
|
uint64_t draw_sampler_full_update_;
|
||||||
|
|
||||||
|
// Hashes of the current texture descriptor layout.
|
||||||
|
uint64_t texture_bindings_hash_vertex_;
|
||||||
|
uint64_t texture_bindings_hash_pixel_;
|
||||||
|
|
||||||
// Latest descriptor handles used for handling Xenos draw calls.
|
// Latest descriptor handles used for handling Xenos draw calls.
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_system_constants_;
|
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_system_constants_;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_vertex_float_constants_;
|
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_vertex_float_constants_;
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include "xenia/gpu/d3d12/texture_cache.h"
|
#include "xenia/gpu/d3d12/texture_cache.h"
|
||||||
|
|
||||||
|
#include "third_party/xxhash/xxhash.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -292,7 +294,11 @@ TextureCache::TextureCache(D3D12CommandProcessor* command_processor,
|
||||||
SharedMemory* shared_memory)
|
SharedMemory* shared_memory)
|
||||||
: command_processor_(command_processor),
|
: command_processor_(command_processor),
|
||||||
register_file_(register_file),
|
register_file_(register_file),
|
||||||
shared_memory_(shared_memory) {}
|
shared_memory_(shared_memory) {
|
||||||
|
XXH64_state_t hash_state;
|
||||||
|
XXH64_reset(&hash_state, 0);
|
||||||
|
texture_bindings_empty_hash_ = XXH64_digest(&hash_state);
|
||||||
|
}
|
||||||
|
|
||||||
TextureCache::~TextureCache() { Shutdown(); }
|
TextureCache::~TextureCache() { Shutdown(); }
|
||||||
|
|
||||||
|
@ -427,7 +433,9 @@ void TextureCache::EndFrame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask,
|
void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask,
|
||||||
uint32_t used_pixel_texture_mask) {
|
uint32_t used_pixel_texture_mask,
|
||||||
|
uint64_t& descriptor_layout_vertex_hash_out,
|
||||||
|
uint64_t& descriptor_layout_pixel_hash_out) {
|
||||||
auto command_list = command_processor_->GetCurrentCommandList();
|
auto command_list = command_processor_->GetCurrentCommandList();
|
||||||
if (command_list == nullptr) {
|
if (command_list == nullptr) {
|
||||||
return;
|
return;
|
||||||
|
@ -498,6 +506,31 @@ void TextureCache::RequestTextures(uint32_t used_vertex_texture_mask,
|
||||||
state);
|
state);
|
||||||
texture->state = state;
|
texture->state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute descriptor layout hashes so descriptors don't have to be written
|
||||||
|
// again if the bindings are the same. The hash is computed from indices, keys
|
||||||
|
// and swizzles.
|
||||||
|
XXH64_state_t hash_state;
|
||||||
|
XXH64_reset(&hash_state, 0);
|
||||||
|
used_texture_mask = used_vertex_texture_mask;
|
||||||
|
while (xe::bit_scan_forward(used_texture_mask, &index)) {
|
||||||
|
used_texture_mask &= ~(1u << index);
|
||||||
|
XXH64_update(&hash_state, &index, sizeof(index));
|
||||||
|
const TextureBinding& binding = texture_bindings_[index];
|
||||||
|
XXH64_update(&hash_state, &binding.key, sizeof(binding.key));
|
||||||
|
XXH64_update(&hash_state, &binding.swizzle, sizeof(binding.swizzle));
|
||||||
|
}
|
||||||
|
descriptor_layout_vertex_hash_out = XXH64_digest(&hash_state);
|
||||||
|
XXH64_reset(&hash_state, 0);
|
||||||
|
used_texture_mask = used_pixel_texture_mask;
|
||||||
|
while (xe::bit_scan_forward(used_texture_mask, &index)) {
|
||||||
|
used_texture_mask &= ~(1u << index);
|
||||||
|
XXH64_update(&hash_state, &index, sizeof(index));
|
||||||
|
const TextureBinding& binding = texture_bindings_[index];
|
||||||
|
XXH64_update(&hash_state, &binding.key, sizeof(binding.key));
|
||||||
|
XXH64_update(&hash_state, &binding.swizzle, sizeof(binding.swizzle));
|
||||||
|
}
|
||||||
|
descriptor_layout_pixel_hash_out = XXH64_digest(&hash_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::WriteTextureSRV(uint32_t fetch_constant,
|
void TextureCache::WriteTextureSRV(uint32_t fetch_constant,
|
||||||
|
|
|
@ -72,7 +72,12 @@ class TextureCache {
|
||||||
// (notifying the command processor about that), so this must be called before
|
// (notifying the command processor about that), so this must be called before
|
||||||
// binding the actual drawing pipeline.
|
// binding the actual drawing pipeline.
|
||||||
void RequestTextures(uint32_t used_vertex_texture_mask,
|
void RequestTextures(uint32_t used_vertex_texture_mask,
|
||||||
uint32_t used_pixel_texture_mask);
|
uint32_t used_pixel_texture_mask,
|
||||||
|
uint64_t& descriptor_layout_vertex_hash_out,
|
||||||
|
uint64_t& descriptor_layout_pixel_hash_out);
|
||||||
|
inline uint64_t GetEmptyTextureBindingsHash() const {
|
||||||
|
return texture_bindings_empty_hash_;
|
||||||
|
}
|
||||||
|
|
||||||
void WriteTextureSRV(uint32_t fetch_constant,
|
void WriteTextureSRV(uint32_t fetch_constant,
|
||||||
TextureDimension shader_dimension,
|
TextureDimension shader_dimension,
|
||||||
|
@ -366,6 +371,8 @@ class TextureCache {
|
||||||
std::unordered_multimap<uint64_t, Texture*> textures_;
|
std::unordered_multimap<uint64_t, Texture*> textures_;
|
||||||
|
|
||||||
TextureBinding texture_bindings_[32] = {};
|
TextureBinding texture_bindings_[32] = {};
|
||||||
|
// Hash for no textures bound.
|
||||||
|
uint64_t texture_bindings_empty_hash_;
|
||||||
// Bit vector with bits reset on fetch constant writes to avoid getting
|
// Bit vector with bits reset on fetch constant writes to avoid getting
|
||||||
// texture keys from the fetch constants again and again.
|
// texture keys from the fetch constants again and again.
|
||||||
uint32_t texture_keys_in_sync_ = 0;
|
uint32_t texture_keys_in_sync_ = 0;
|
||||||
|
|
Loading…
Reference in New Issue