[D3D12] Compact float constants and don't split them into pages

This commit is contained in:
Triang3l
2018-09-30 20:17:26 +03:00
parent eb50ebd885
commit c4599ff211
7 changed files with 733 additions and 485 deletions

View File

@@ -175,7 +175,8 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
range.NumDescriptors = 1;
range.BaseShaderRegister = 2;
range.BaseShaderRegister =
uint32_t(DxbcShaderTranslator::CbufferRegister::kFetchConstants);
range.RegisterSpace = 0;
range.OffsetInDescriptorsFromTableStart = 0;
}
@@ -189,8 +190,9 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
parameter.DescriptorTable.pDescriptorRanges = ⦥
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
range.NumDescriptors = 8;
range.BaseShaderRegister = 3;
range.NumDescriptors = 1;
range.BaseShaderRegister =
uint32_t(DxbcShaderTranslator::CbufferRegister::kFloatConstants);
range.RegisterSpace = 0;
range.OffsetInDescriptorsFromTableStart = 0;
}
@@ -204,8 +206,9 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
parameter.DescriptorTable.pDescriptorRanges = ⦥
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
range.NumDescriptors = 8;
range.BaseShaderRegister = 3;
range.NumDescriptors = 1;
range.BaseShaderRegister =
uint32_t(DxbcShaderTranslator::CbufferRegister::kFloatConstants);
range.RegisterSpace = 0;
range.OffsetInDescriptorsFromTableStart = 0;
}
@@ -220,7 +223,8 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
range.NumDescriptors = 2;
range.BaseShaderRegister = 0;
range.BaseShaderRegister =
uint32_t(DxbcShaderTranslator::CbufferRegister::kSystemConstants);
range.RegisterSpace = 0;
range.OffsetInDescriptorsFromTableStart = 0;
}
@@ -741,8 +745,22 @@ void D3D12CommandProcessor::WriteRegister(uint32_t index, uint32_t value) {
if (index >= XE_GPU_REG_SHADER_CONSTANT_000_X &&
index <= XE_GPU_REG_SHADER_CONSTANT_511_W) {
uint32_t component_index = index - XE_GPU_REG_SHADER_CONSTANT_000_X;
cbuffer_bindings_float_[component_index >> 7].up_to_date = false;
if (current_queue_frame_ != UINT32_MAX) {
uint32_t float_constant_index =
(index - XE_GPU_REG_SHADER_CONSTANT_000_X) >> 2;
if (float_constant_index >= 256) {
float_constant_index -= 256;
if (float_constant_map_pixel_[float_constant_index >> 6] &
(1ull << (float_constant_index & 63))) {
cbuffer_bindings_pixel_float_.up_to_date = false;
}
} else {
if (float_constant_map_vertex_[float_constant_index >> 6] &
(1ull << (float_constant_index & 63))) {
cbuffer_bindings_vertex_float_.up_to_date = false;
}
}
}
} else if (index >= XE_GPU_REG_SHADER_CONSTANT_BOOL_000_031 &&
index <= XE_GPU_REG_SHADER_CONSTANT_LOOP_31) {
cbuffer_bindings_bool_loop_.up_to_date = false;
@@ -1145,10 +1163,12 @@ bool D3D12CommandProcessor::BeginFrame() {
current_graphics_root_up_to_date_ = 0;
current_view_heap_ = nullptr;
current_sampler_heap_ = nullptr;
std::memset(float_constant_map_vertex_, 0,
sizeof(float_constant_map_vertex_));
std::memset(float_constant_map_pixel_, 0, sizeof(float_constant_map_pixel_));
cbuffer_bindings_system_.up_to_date = false;
for (uint32_t i = 0; i < xe::countof(cbuffer_bindings_float_); ++i) {
cbuffer_bindings_float_[i].up_to_date = false;
}
cbuffer_bindings_vertex_float_.up_to_date = false;
cbuffer_bindings_pixel_float_.up_to_date = false;
cbuffer_bindings_bool_loop_.up_to_date = false;
cbuffer_bindings_fetch_.up_to_date = false;
draw_view_full_update_ = 0;
@@ -1657,14 +1677,64 @@ bool D3D12CommandProcessor::UpdateBindings(
// Begin updating descriptors.
bool write_common_constant_views = false;
bool write_vertex_float_constant_view = false;
bool write_pixel_float_constant_view = false;
bool write_fetch_constant_view = false;
bool write_vertex_float_constant_views = false;
bool write_pixel_float_constant_views = false;
// TODO(Triang3l): Update textures and samplers only if shaders or binding
// hash change.
bool write_textures = texture_count != 0;
bool write_samplers = sampler_count != 0;
// Check if the float constant layout is still the same and get the counts.
const Shader::ConstantRegisterMap& vertex_shader_float_constant_map =
vertex_shader->constant_register_map();
uint32_t vertex_shader_float_constant_count =
vertex_shader_float_constant_map.float_count;
// Even if the shader doesn't need any float constants, a valid binding must
// still be provided, so if the first draw in the frame with the current root
// signature doesn't have float constants at all, still allocate an empty
// buffer.
uint32_t vertex_shader_float_constant_size =
xe::align(uint32_t(std::max(vertex_shader_float_constant_count, 1u) * 4 *
sizeof(float)),
256u);
for (uint32_t i = 0; i < 4; ++i) {
if (float_constant_map_vertex_[i] !=
vertex_shader_float_constant_map.float_bitmap[i]) {
float_constant_map_vertex_[i] =
vertex_shader_float_constant_map.float_bitmap[i];
// If no float constants at all, we can reuse any buffer for them, so not
// invalidating.
if (vertex_shader_float_constant_map.float_count != 0) {
cbuffer_bindings_vertex_float_.up_to_date = false;
}
}
}
uint32_t pixel_shader_float_constant_count = 0;
if (pixel_shader != nullptr) {
const Shader::ConstantRegisterMap& pixel_shader_float_constant_map =
pixel_shader->constant_register_map();
pixel_shader_float_constant_count =
pixel_shader_float_constant_map.float_count;
for (uint32_t i = 0; i < 4; ++i) {
if (float_constant_map_pixel_[i] !=
pixel_shader_float_constant_map.float_bitmap[i]) {
float_constant_map_pixel_[i] =
pixel_shader_float_constant_map.float_bitmap[i];
if (pixel_shader_float_constant_map.float_count != 0) {
cbuffer_bindings_pixel_float_.up_to_date = false;
}
}
}
} else {
std::memset(float_constant_map_pixel_, 0,
sizeof(float_constant_map_pixel_));
}
uint32_t pixel_shader_float_constant_size =
xe::align(uint32_t(std::max(pixel_shader_float_constant_count, 1u) * 4 *
sizeof(float)),
256u);
// Update constant buffers.
if (!cbuffer_bindings_system_.up_to_date) {
uint8_t* system_constants = constant_buffer_pool_->RequestFull(
@@ -1678,6 +1748,60 @@ bool D3D12CommandProcessor::UpdateBindings(
cbuffer_bindings_system_.up_to_date = true;
write_common_constant_views = true;
}
if (!cbuffer_bindings_vertex_float_.up_to_date) {
uint8_t* float_constants = constant_buffer_pool_->RequestFull(
vertex_shader_float_constant_size, nullptr, nullptr,
&cbuffer_bindings_vertex_float_.buffer_address);
if (float_constants == nullptr) {
return false;
}
for (uint32_t i = 0; i < 4; ++i) {
uint64_t float_constant_map_entry =
vertex_shader_float_constant_map.float_bitmap[i];
uint32_t float_constant_index;
while (xe::bit_scan_forward(float_constant_map_entry,
&float_constant_index)) {
float_constant_map_entry &= ~(1ull << float_constant_index);
std::memcpy(float_constants,
&regs[XE_GPU_REG_SHADER_CONSTANT_000_X + (i << 8) +
(float_constant_index << 2)]
.f32,
4 * sizeof(float));
float_constants += 4 * sizeof(float);
}
}
cbuffer_bindings_vertex_float_.up_to_date = true;
write_vertex_float_constant_view = true;
}
if (!cbuffer_bindings_pixel_float_.up_to_date) {
uint8_t* float_constants = constant_buffer_pool_->RequestFull(
pixel_shader_float_constant_size, nullptr, nullptr,
&cbuffer_bindings_pixel_float_.buffer_address);
if (float_constants == nullptr) {
return false;
}
if (pixel_shader != nullptr) {
const Shader::ConstantRegisterMap& pixel_shader_float_constant_map =
pixel_shader->constant_register_map();
for (uint32_t i = 0; i < 4; ++i) {
uint64_t float_constant_map_entry =
pixel_shader_float_constant_map.float_bitmap[i];
uint32_t float_constant_index;
while (xe::bit_scan_forward(float_constant_map_entry,
&float_constant_index)) {
float_constant_map_entry &= ~(1ull << float_constant_index);
std::memcpy(float_constants,
&regs[XE_GPU_REG_SHADER_CONSTANT_256_X + (i << 8) +
(float_constant_index << 2)]
.f32,
4 * sizeof(float));
float_constants += 4 * sizeof(float);
}
}
}
cbuffer_bindings_pixel_float_.up_to_date = true;
write_pixel_float_constant_view = true;
}
if (!cbuffer_bindings_bool_loop_.up_to_date) {
uint32_t* bool_loop_constants =
reinterpret_cast<uint32_t*>(constant_buffer_pool_->RequestFull(
@@ -1711,26 +1835,6 @@ bool D3D12CommandProcessor::UpdateBindings(
cbuffer_bindings_fetch_.up_to_date = true;
write_fetch_constant_view = true;
}
for (uint32_t i = 0; i < 16; ++i) {
ConstantBufferBinding& float_binding = cbuffer_bindings_float_[i];
if (float_binding.up_to_date) {
continue;
}
uint8_t* float_constants = constant_buffer_pool_->RequestFull(
512, nullptr, nullptr, &float_binding.buffer_address);
if (float_constants == nullptr) {
return false;
}
std::memcpy(float_constants,
&regs[XE_GPU_REG_SHADER_CONSTANT_000_X + (i << 7)].f32,
32 * 4 * sizeof(uint32_t));
float_binding.up_to_date = true;
if (i < 8) {
write_vertex_float_constant_views = true;
} else {
write_pixel_float_constant_views = true;
}
}
// Allocate the descriptors.
uint32_t view_count_partial_update = 0;
@@ -1738,18 +1842,18 @@ bool D3D12CommandProcessor::UpdateBindings(
// System and bool/loop constants.
view_count_partial_update += 2;
}
if (write_vertex_float_constant_view) {
// Vertex float constants.
++view_count_partial_update;
}
if (write_pixel_float_constant_view) {
// Pixel float constants.
++view_count_partial_update;
}
if (write_fetch_constant_view) {
// Fetch constants.
++view_count_partial_update;
}
if (write_vertex_float_constant_views) {
// Vertex float constants.
view_count_partial_update += 8;
}
if (write_pixel_float_constant_views) {
// Pixel float constants.
view_count_partial_update += 8;
}
if (write_textures) {
view_count_partial_update += texture_count;
}
@@ -1783,8 +1887,8 @@ bool D3D12CommandProcessor::UpdateBindings(
draw_view_full_update_ = view_full_update_index;
write_common_constant_views = true;
write_fetch_constant_view = true;
write_vertex_float_constant_views = true;
write_pixel_float_constant_views = true;
write_vertex_float_constant_view = true;
write_pixel_float_constant_view = true;
write_textures = texture_count != 0;
// If updating fully, write the shared memory descriptor (t0, space1).
shared_memory_->CreateSRV(view_cpu_handle);
@@ -1821,9 +1925,33 @@ bool D3D12CommandProcessor::UpdateBindings(
current_graphics_root_up_to_date_ &=
~(1u << kRootParameter_CommonConstants);
}
if (write_vertex_float_constant_view) {
gpu_handle_vertex_float_constants_ = view_gpu_handle;
// Vertex float constants (b2).
constant_buffer_desc.BufferLocation =
cbuffer_bindings_vertex_float_.buffer_address;
constant_buffer_desc.SizeInBytes = vertex_shader_float_constant_size;
device->CreateConstantBufferView(&constant_buffer_desc, view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
current_graphics_root_up_to_date_ &=
~(1u << kRootParameter_VertexFloatConstants);
}
if (write_pixel_float_constant_view) {
gpu_handle_pixel_float_constants_ = view_gpu_handle;
// Pixel float constants (b2).
constant_buffer_desc.BufferLocation =
cbuffer_bindings_pixel_float_.buffer_address;
constant_buffer_desc.SizeInBytes = pixel_shader_float_constant_size;
device->CreateConstantBufferView(&constant_buffer_desc, view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
current_graphics_root_up_to_date_ &=
~(1u << kRootParameter_PixelFloatConstants);
}
if (write_fetch_constant_view) {
gpu_handle_fetch_constants_ = view_gpu_handle;
// Fetch constants (b2).
// Fetch constants (b3).
constant_buffer_desc.BufferLocation =
cbuffer_bindings_fetch_.buffer_address;
constant_buffer_desc.SizeInBytes = 768;
@@ -1832,34 +1960,6 @@ bool D3D12CommandProcessor::UpdateBindings(
view_gpu_handle.ptr += descriptor_size_view;
current_graphics_root_up_to_date_ &= ~(1u << kRootParameter_FetchConstants);
}
if (write_vertex_float_constant_views) {
gpu_handle_vertex_float_constants_ = view_gpu_handle;
// Vertex float constants (b3-b10).
for (uint32_t i = 0; i < 8; ++i) {
constant_buffer_desc.BufferLocation =
cbuffer_bindings_float_[i].buffer_address;
constant_buffer_desc.SizeInBytes = 512;
device->CreateConstantBufferView(&constant_buffer_desc, view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
}
current_graphics_root_up_to_date_ &=
~(1u << kRootParameter_VertexFloatConstants);
}
if (write_pixel_float_constant_views) {
gpu_handle_pixel_float_constants_ = view_gpu_handle;
// Pixel float constants (b3-b10).
for (uint32_t i = 0; i < 8; ++i) {
constant_buffer_desc.BufferLocation =
cbuffer_bindings_float_[8 + i].buffer_address;
constant_buffer_desc.SizeInBytes = 512;
device->CreateConstantBufferView(&constant_buffer_desc, view_cpu_handle);
view_cpu_handle.ptr += descriptor_size_view;
view_gpu_handle.ptr += descriptor_size_view;
}
current_graphics_root_up_to_date_ &=
~(1u << kRootParameter_PixelFloatConstants);
}
if (write_textures) {
if (pixel_texture_count != 0) {
assert_true(current_graphics_root_extras_.pixel_textures !=