[D3D12] Hash sampler bindings and refactor names in UpdateBindings
This commit is contained in:
parent
3de2b5e692
commit
685d3074f4
|
@ -10,6 +10,7 @@
|
|||
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include "third_party/xxhash/xxhash.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
@ -126,24 +127,26 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
assert_true(vertex_shader->is_translated());
|
||||
assert_true(pixel_shader == nullptr || pixel_shader->is_translated());
|
||||
|
||||
uint32_t pixel_texture_count = 0, pixel_sampler_count = 0;
|
||||
uint32_t texture_count_vertex, sampler_count_vertex;
|
||||
vertex_shader->GetTextureSRVs(texture_count_vertex);
|
||||
vertex_shader->GetSamplerBindings(sampler_count_vertex);
|
||||
uint32_t texture_count_pixel = 0, sampler_count_pixel = 0;
|
||||
if (pixel_shader != nullptr) {
|
||||
pixel_shader->GetTextureSRVs(pixel_texture_count);
|
||||
pixel_shader->GetSamplerBindings(pixel_sampler_count);
|
||||
pixel_shader->GetTextureSRVs(texture_count_pixel);
|
||||
pixel_shader->GetSamplerBindings(sampler_count_pixel);
|
||||
}
|
||||
uint32_t vertex_texture_count, vertex_sampler_count;
|
||||
vertex_shader->GetTextureSRVs(vertex_texture_count);
|
||||
vertex_shader->GetSamplerBindings(vertex_sampler_count);
|
||||
|
||||
// Better put the pixel texture/sampler in the lower bits probably because it
|
||||
// changes often.
|
||||
uint32_t index = 0;
|
||||
uint32_t index_offset = 0;
|
||||
index |= pixel_texture_count << index_offset;
|
||||
index |= texture_count_pixel << index_offset;
|
||||
index_offset += D3D12Shader::kMaxTextureSRVIndexBits;
|
||||
index |= pixel_sampler_count << index_offset;
|
||||
index |= sampler_count_pixel << index_offset;
|
||||
index_offset += D3D12Shader::kMaxSamplerBindingIndexBits;
|
||||
index |= vertex_texture_count << index_offset;
|
||||
index |= texture_count_vertex << index_offset;
|
||||
index_offset += D3D12Shader::kMaxTextureSRVIndexBits;
|
||||
index |= vertex_sampler_count << index_offset;
|
||||
index |= sampler_count_vertex << index_offset;
|
||||
index_offset += D3D12Shader::kMaxSamplerBindingIndexBits;
|
||||
assert_true(index_offset <= 32);
|
||||
|
||||
|
@ -183,8 +186,8 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
|
||||
// Vertex float constants.
|
||||
{
|
||||
auto& parameter = parameters[kRootParameter_VertexFloatConstants];
|
||||
auto& range = ranges[kRootParameter_VertexFloatConstants];
|
||||
auto& parameter = parameters[kRootParameter_FloatConstantsVertex];
|
||||
auto& range = ranges[kRootParameter_FloatConstantsVertex];
|
||||
parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
parameter.DescriptorTable.NumDescriptorRanges = 1;
|
||||
parameter.DescriptorTable.pDescriptorRanges = ⦥
|
||||
|
@ -199,8 +202,8 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
|
||||
// Pixel float constants.
|
||||
{
|
||||
auto& parameter = parameters[kRootParameter_PixelFloatConstants];
|
||||
auto& range = ranges[kRootParameter_PixelFloatConstants];
|
||||
auto& parameter = parameters[kRootParameter_FloatConstantsPixel];
|
||||
auto& range = ranges[kRootParameter_FloatConstantsPixel];
|
||||
parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
parameter.DescriptorTable.NumDescriptorRanges = 1;
|
||||
parameter.DescriptorTable.pDescriptorRanges = ⦥
|
||||
|
@ -263,7 +266,7 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
// Extra parameters.
|
||||
|
||||
// Pixel textures.
|
||||
if (pixel_texture_count > 0) {
|
||||
if (texture_count_pixel > 0) {
|
||||
auto& parameter = parameters[desc.NumParameters];
|
||||
auto& range = ranges[desc.NumParameters];
|
||||
parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
|
@ -271,7 +274,7 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
parameter.DescriptorTable.pDescriptorRanges = ⦥
|
||||
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
range.NumDescriptors = pixel_texture_count;
|
||||
range.NumDescriptors = texture_count_pixel;
|
||||
range.BaseShaderRegister = 1;
|
||||
range.RegisterSpace = 0;
|
||||
range.OffsetInDescriptorsFromTableStart = 0;
|
||||
|
@ -279,7 +282,7 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
}
|
||||
|
||||
// Pixel samplers.
|
||||
if (pixel_sampler_count > 0) {
|
||||
if (sampler_count_pixel > 0) {
|
||||
auto& parameter = parameters[desc.NumParameters];
|
||||
auto& range = ranges[desc.NumParameters];
|
||||
parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
|
@ -287,7 +290,7 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
parameter.DescriptorTable.pDescriptorRanges = ⦥
|
||||
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||
range.NumDescriptors = pixel_sampler_count;
|
||||
range.NumDescriptors = sampler_count_pixel;
|
||||
range.BaseShaderRegister = 0;
|
||||
range.RegisterSpace = 0;
|
||||
range.OffsetInDescriptorsFromTableStart = 0;
|
||||
|
@ -295,7 +298,7 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
}
|
||||
|
||||
// Vertex textures.
|
||||
if (vertex_texture_count > 0) {
|
||||
if (texture_count_vertex > 0) {
|
||||
auto& parameter = parameters[desc.NumParameters];
|
||||
auto& range = ranges[desc.NumParameters];
|
||||
parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
|
@ -303,7 +306,7 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
parameter.DescriptorTable.pDescriptorRanges = ⦥
|
||||
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
|
||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||
range.NumDescriptors = vertex_texture_count;
|
||||
range.NumDescriptors = texture_count_vertex;
|
||||
range.BaseShaderRegister = 1;
|
||||
range.RegisterSpace = 0;
|
||||
range.OffsetInDescriptorsFromTableStart = 0;
|
||||
|
@ -311,7 +314,7 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
}
|
||||
|
||||
// Vertex samplers.
|
||||
if (vertex_sampler_count > 0) {
|
||||
if (sampler_count_vertex > 0) {
|
||||
auto& parameter = parameters[desc.NumParameters];
|
||||
auto& range = ranges[desc.NumParameters];
|
||||
parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
|
@ -319,7 +322,7 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
parameter.DescriptorTable.pDescriptorRanges = ⦥
|
||||
parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
|
||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||
range.NumDescriptors = vertex_sampler_count;
|
||||
range.NumDescriptors = sampler_count_vertex;
|
||||
range.BaseShaderRegister = 0;
|
||||
range.RegisterSpace = 0;
|
||||
range.OffsetInDescriptorsFromTableStart = 0;
|
||||
|
@ -332,8 +335,8 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
XELOGE(
|
||||
"Failed to create a root signature with %u pixel textures, %u pixel "
|
||||
"samplers, %u vertex textures and %u vertex samplers",
|
||||
pixel_texture_count, pixel_sampler_count, vertex_texture_count,
|
||||
vertex_sampler_count);
|
||||
texture_count_pixel, sampler_count_pixel, texture_count_vertex,
|
||||
sampler_count_vertex);
|
||||
return nullptr;
|
||||
}
|
||||
root_signatures_.insert({index, root_signature});
|
||||
|
@ -343,35 +346,35 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
|
|||
uint32_t D3D12CommandProcessor::GetRootExtraParameterIndices(
|
||||
const D3D12Shader* vertex_shader, const D3D12Shader* pixel_shader,
|
||||
RootExtraParameterIndices& indices_out) {
|
||||
uint32_t pixel_texture_count = 0, pixel_sampler_count = 0;
|
||||
uint32_t texture_count_pixel = 0, sampler_count_pixel = 0;
|
||||
if (pixel_shader != nullptr) {
|
||||
pixel_shader->GetTextureSRVs(pixel_texture_count);
|
||||
pixel_shader->GetSamplerBindings(pixel_sampler_count);
|
||||
pixel_shader->GetTextureSRVs(texture_count_pixel);
|
||||
pixel_shader->GetSamplerBindings(sampler_count_pixel);
|
||||
}
|
||||
uint32_t vertex_texture_count, vertex_sampler_count;
|
||||
vertex_shader->GetTextureSRVs(vertex_texture_count);
|
||||
vertex_shader->GetSamplerBindings(vertex_sampler_count);
|
||||
uint32_t texture_count_vertex, sampler_count_vertex;
|
||||
vertex_shader->GetTextureSRVs(texture_count_vertex);
|
||||
vertex_shader->GetSamplerBindings(sampler_count_vertex);
|
||||
|
||||
uint32_t index = kRootParameter_Count_Base;
|
||||
if (pixel_texture_count != 0) {
|
||||
indices_out.pixel_textures = index++;
|
||||
if (texture_count_pixel != 0) {
|
||||
indices_out.textures_pixel = index++;
|
||||
} else {
|
||||
indices_out.pixel_textures = RootExtraParameterIndices::kUnavailable;
|
||||
indices_out.textures_pixel = RootExtraParameterIndices::kUnavailable;
|
||||
}
|
||||
if (pixel_sampler_count != 0) {
|
||||
indices_out.pixel_samplers = index++;
|
||||
if (sampler_count_pixel != 0) {
|
||||
indices_out.samplers_pixel = index++;
|
||||
} else {
|
||||
indices_out.pixel_samplers = RootExtraParameterIndices::kUnavailable;
|
||||
indices_out.samplers_pixel = RootExtraParameterIndices::kUnavailable;
|
||||
}
|
||||
if (vertex_texture_count != 0) {
|
||||
indices_out.vertex_textures = index++;
|
||||
if (texture_count_vertex != 0) {
|
||||
indices_out.textures_vertex = index++;
|
||||
} else {
|
||||
indices_out.vertex_textures = RootExtraParameterIndices::kUnavailable;
|
||||
indices_out.textures_vertex = RootExtraParameterIndices::kUnavailable;
|
||||
}
|
||||
if (vertex_sampler_count != 0) {
|
||||
indices_out.vertex_samplers = index++;
|
||||
if (sampler_count_vertex != 0) {
|
||||
indices_out.samplers_vertex = index++;
|
||||
} else {
|
||||
indices_out.vertex_samplers = RootExtraParameterIndices::kUnavailable;
|
||||
indices_out.samplers_vertex = RootExtraParameterIndices::kUnavailable;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
@ -826,14 +829,14 @@ void D3D12CommandProcessor::WriteRegister(uint32_t index, uint32_t value) {
|
|||
(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] &
|
||||
if (current_float_constant_map_pixel_[float_constant_index >> 6] &
|
||||
(1ull << (float_constant_index & 63))) {
|
||||
cbuffer_bindings_pixel_float_.up_to_date = false;
|
||||
cbuffer_bindings_float_pixel_.up_to_date = false;
|
||||
}
|
||||
} else {
|
||||
if (float_constant_map_vertex_[float_constant_index >> 6] &
|
||||
if (current_float_constant_map_vertex_[float_constant_index >> 6] &
|
||||
(1ull << (float_constant_index & 63))) {
|
||||
cbuffer_bindings_vertex_float_.up_to_date = false;
|
||||
cbuffer_bindings_float_vertex_.up_to_date = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1303,18 +1306,21 @@ 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_));
|
||||
std::memset(current_float_constant_map_vertex_, 0,
|
||||
sizeof(current_float_constant_map_vertex_));
|
||||
std::memset(current_float_constant_map_pixel_, 0,
|
||||
sizeof(current_float_constant_map_pixel_));
|
||||
cbuffer_bindings_system_.up_to_date = false;
|
||||
cbuffer_bindings_vertex_float_.up_to_date = false;
|
||||
cbuffer_bindings_pixel_float_.up_to_date = false;
|
||||
cbuffer_bindings_float_vertex_.up_to_date = false;
|
||||
cbuffer_bindings_float_pixel_.up_to_date = false;
|
||||
cbuffer_bindings_bool_loop_.up_to_date = false;
|
||||
cbuffer_bindings_fetch_.up_to_date = false;
|
||||
draw_view_full_update_ = 0;
|
||||
draw_sampler_full_update_ = 0;
|
||||
texture_bindings_written_vertex_ = false;
|
||||
texture_bindings_written_pixel_ = false;
|
||||
samplers_written_vertex_ = false;
|
||||
samplers_written_pixel_ = false;
|
||||
primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||
|
||||
command_lists_[current_queue_frame_]->BeginRecording();
|
||||
|
@ -1796,102 +1802,121 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
command_list->SetGraphicsRootSignature(root_signature);
|
||||
}
|
||||
|
||||
// Get used textures and samplers.
|
||||
uint32_t pixel_texture_count, pixel_sampler_count;
|
||||
const D3D12Shader::TextureSRV* pixel_textures;
|
||||
const D3D12Shader::SamplerBinding* pixel_samplers;
|
||||
if (pixel_shader != nullptr) {
|
||||
pixel_textures = pixel_shader->GetTextureSRVs(pixel_texture_count);
|
||||
pixel_samplers = pixel_shader->GetSamplerBindings(pixel_sampler_count);
|
||||
} else {
|
||||
pixel_textures = nullptr;
|
||||
pixel_texture_count = 0;
|
||||
pixel_samplers = nullptr;
|
||||
pixel_sampler_count = 0;
|
||||
XXH64_state_t hash_state;
|
||||
|
||||
// Get textures and samplers used by the vertex shader.
|
||||
uint32_t texture_count_vertex, sampler_count_vertex;
|
||||
const D3D12Shader::TextureSRV* textures_vertex =
|
||||
vertex_shader->GetTextureSRVs(texture_count_vertex);
|
||||
uint64_t texture_bindings_hash_vertex =
|
||||
texture_count_vertex != 0
|
||||
? texture_cache_->GetDescriptorHashForActiveTextures(
|
||||
textures_vertex, texture_count_vertex)
|
||||
: 0;
|
||||
const D3D12Shader::SamplerBinding* samplers_vertex =
|
||||
vertex_shader->GetSamplerBindings(sampler_count_vertex);
|
||||
XXH64_reset(&hash_state, 0);
|
||||
for (uint32_t i = 0; i < sampler_count_vertex; ++i) {
|
||||
TextureCache::SamplerParameters sampler_parameters =
|
||||
texture_cache_->GetSamplerParameters(samplers_vertex[i]);
|
||||
XXH64_update(&hash_state, &sampler_parameters, sizeof(sampler_parameters));
|
||||
}
|
||||
uint64_t new_pixel_texture_bindings_hash =
|
||||
pixel_texture_count != 0
|
||||
uint64_t samplers_hash_vertex = XXH64_digest(&hash_state);
|
||||
|
||||
// Get textures and samplers used by the pixel shader.
|
||||
uint32_t texture_count_pixel, sampler_count_pixel;
|
||||
const D3D12Shader::TextureSRV* textures_pixel;
|
||||
const D3D12Shader::SamplerBinding* samplers_pixel;
|
||||
if (pixel_shader != nullptr) {
|
||||
textures_pixel = pixel_shader->GetTextureSRVs(texture_count_pixel);
|
||||
samplers_pixel = pixel_shader->GetSamplerBindings(sampler_count_pixel);
|
||||
} else {
|
||||
textures_pixel = nullptr;
|
||||
texture_count_pixel = 0;
|
||||
samplers_pixel = nullptr;
|
||||
sampler_count_pixel = 0;
|
||||
}
|
||||
uint64_t texture_bindings_hash_pixel =
|
||||
texture_count_pixel != 0
|
||||
? texture_cache_->GetDescriptorHashForActiveTextures(
|
||||
pixel_textures, pixel_texture_count)
|
||||
textures_pixel, texture_count_pixel)
|
||||
: 0;
|
||||
uint32_t vertex_texture_count, vertex_sampler_count;
|
||||
const D3D12Shader::TextureSRV* vertex_textures =
|
||||
vertex_shader->GetTextureSRVs(vertex_texture_count);
|
||||
uint64_t new_vertex_texture_bindings_hash =
|
||||
vertex_texture_count != 0
|
||||
? texture_cache_->GetDescriptorHashForActiveTextures(
|
||||
vertex_textures, vertex_texture_count)
|
||||
: 0;
|
||||
const D3D12Shader::SamplerBinding* vertex_samplers =
|
||||
vertex_shader->GetSamplerBindings(vertex_sampler_count);
|
||||
uint32_t sampler_count = pixel_sampler_count + vertex_sampler_count;
|
||||
XXH64_reset(&hash_state, 0);
|
||||
for (uint32_t i = 0; i < sampler_count_pixel; ++i) {
|
||||
TextureCache::SamplerParameters sampler_parameters =
|
||||
texture_cache_->GetSamplerParameters(samplers_pixel[i]);
|
||||
XXH64_update(&hash_state, &sampler_parameters, sizeof(sampler_parameters));
|
||||
}
|
||||
uint64_t samplers_hash_pixel = XXH64_digest(&hash_state);
|
||||
|
||||
// Begin updating descriptors.
|
||||
bool write_system_constant_view = false;
|
||||
bool write_vertex_float_constant_view = false;
|
||||
bool write_pixel_float_constant_view = false;
|
||||
bool write_float_constant_view_vertex = false;
|
||||
bool write_float_constant_view_pixel = false;
|
||||
bool write_bool_loop_constant_view = false;
|
||||
bool write_fetch_constant_view = false;
|
||||
// TODO(Triang3l): Update samplers only if shaders or binding hash change.
|
||||
bool write_vertex_textures =
|
||||
vertex_texture_count != 0 &&
|
||||
bool write_textures_vertex =
|
||||
texture_count_vertex != 0 &&
|
||||
(!texture_bindings_written_vertex_ ||
|
||||
texture_bindings_hash_vertex_ != new_vertex_texture_bindings_hash);
|
||||
bool write_pixel_textures =
|
||||
pixel_texture_count != 0 &&
|
||||
current_texture_bindings_hash_vertex_ != texture_bindings_hash_vertex);
|
||||
bool write_textures_pixel =
|
||||
texture_count_pixel != 0 &&
|
||||
(!texture_bindings_written_pixel_ ||
|
||||
texture_bindings_hash_pixel_ != new_pixel_texture_bindings_hash);
|
||||
bool write_samplers = sampler_count != 0;
|
||||
current_texture_bindings_hash_pixel_ != texture_bindings_hash_pixel);
|
||||
bool write_samplers_vertex =
|
||||
sampler_count_vertex != 0 &&
|
||||
(!samplers_written_vertex_ ||
|
||||
current_samplers_hash_vertex_ != samplers_hash_vertex);
|
||||
bool write_samplers_pixel =
|
||||
sampler_count_pixel != 0 &&
|
||||
(!samplers_written_pixel_ ||
|
||||
current_samplers_hash_pixel_ != samplers_hash_pixel);
|
||||
|
||||
// Check if the float constant layout is still the same and get the counts.
|
||||
const Shader::ConstantRegisterMap& vertex_shader_float_constant_map =
|
||||
const Shader::ConstantRegisterMap& float_constant_map_vertex =
|
||||
vertex_shader->constant_register_map();
|
||||
uint32_t vertex_shader_float_constant_count =
|
||||
vertex_shader_float_constant_map.float_count;
|
||||
uint32_t float_constant_count_vertex = float_constant_map_vertex.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);
|
||||
uint32_t float_constant_size_vertex = xe::align(
|
||||
uint32_t(std::max(float_constant_count_vertex, 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 (current_float_constant_map_vertex_[i] !=
|
||||
float_constant_map_vertex.float_bitmap[i]) {
|
||||
current_float_constant_map_vertex_[i] =
|
||||
float_constant_map_vertex.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;
|
||||
if (float_constant_map_vertex.float_count != 0) {
|
||||
cbuffer_bindings_float_vertex_.up_to_date = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t pixel_shader_float_constant_count = 0;
|
||||
uint32_t float_constant_count_pixel = 0;
|
||||
if (pixel_shader != nullptr) {
|
||||
const Shader::ConstantRegisterMap& pixel_shader_float_constant_map =
|
||||
const Shader::ConstantRegisterMap& float_constant_map_pixel =
|
||||
pixel_shader->constant_register_map();
|
||||
pixel_shader_float_constant_count =
|
||||
pixel_shader_float_constant_map.float_count;
|
||||
float_constant_count_pixel = float_constant_map_pixel.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;
|
||||
if (current_float_constant_map_pixel_[i] !=
|
||||
float_constant_map_pixel.float_bitmap[i]) {
|
||||
current_float_constant_map_pixel_[i] =
|
||||
float_constant_map_pixel.float_bitmap[i];
|
||||
if (float_constant_map_pixel.float_count != 0) {
|
||||
cbuffer_bindings_float_pixel_.up_to_date = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::memset(float_constant_map_pixel_, 0,
|
||||
sizeof(float_constant_map_pixel_));
|
||||
std::memset(current_float_constant_map_pixel_, 0,
|
||||
sizeof(current_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);
|
||||
uint32_t float_constant_size_pixel = xe::align(
|
||||
uint32_t(std::max(float_constant_count_pixel, 1u) * 4 * sizeof(float)),
|
||||
256u);
|
||||
|
||||
// Update constant buffers.
|
||||
if (!cbuffer_bindings_system_.up_to_date) {
|
||||
|
@ -1906,16 +1931,16 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
cbuffer_bindings_system_.up_to_date = true;
|
||||
write_system_constant_view = true;
|
||||
}
|
||||
if (!cbuffer_bindings_vertex_float_.up_to_date) {
|
||||
if (!cbuffer_bindings_float_vertex_.up_to_date) {
|
||||
uint8_t* float_constants = constant_buffer_pool_->RequestFull(
|
||||
vertex_shader_float_constant_size, nullptr, nullptr,
|
||||
&cbuffer_bindings_vertex_float_.buffer_address);
|
||||
float_constant_size_vertex, nullptr, nullptr,
|
||||
&cbuffer_bindings_float_vertex_.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];
|
||||
float_constant_map_vertex.float_bitmap[i];
|
||||
uint32_t float_constant_index;
|
||||
while (xe::bit_scan_forward(float_constant_map_entry,
|
||||
&float_constant_index)) {
|
||||
|
@ -1928,22 +1953,22 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
float_constants += 4 * sizeof(float);
|
||||
}
|
||||
}
|
||||
cbuffer_bindings_vertex_float_.up_to_date = true;
|
||||
write_vertex_float_constant_view = true;
|
||||
cbuffer_bindings_float_vertex_.up_to_date = true;
|
||||
write_float_constant_view_vertex = true;
|
||||
}
|
||||
if (!cbuffer_bindings_pixel_float_.up_to_date) {
|
||||
if (!cbuffer_bindings_float_pixel_.up_to_date) {
|
||||
uint8_t* float_constants = constant_buffer_pool_->RequestFull(
|
||||
pixel_shader_float_constant_size, nullptr, nullptr,
|
||||
&cbuffer_bindings_pixel_float_.buffer_address);
|
||||
float_constant_size_pixel, nullptr, nullptr,
|
||||
&cbuffer_bindings_float_pixel_.buffer_address);
|
||||
if (float_constants == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (pixel_shader != nullptr) {
|
||||
const Shader::ConstantRegisterMap& pixel_shader_float_constant_map =
|
||||
const Shader::ConstantRegisterMap& float_constant_map_pixel =
|
||||
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];
|
||||
float_constant_map_pixel.float_bitmap[i];
|
||||
uint32_t float_constant_index;
|
||||
while (xe::bit_scan_forward(float_constant_map_entry,
|
||||
&float_constant_index)) {
|
||||
|
@ -1957,8 +1982,8 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
}
|
||||
}
|
||||
}
|
||||
cbuffer_bindings_pixel_float_.up_to_date = true;
|
||||
write_pixel_float_constant_view = true;
|
||||
cbuffer_bindings_float_pixel_.up_to_date = true;
|
||||
write_float_constant_view_pixel = true;
|
||||
}
|
||||
if (!cbuffer_bindings_bool_loop_.up_to_date) {
|
||||
uint32_t* bool_loop_constants =
|
||||
|
@ -1999,10 +2024,10 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
if (write_system_constant_view) {
|
||||
++view_count_partial_update;
|
||||
}
|
||||
if (write_vertex_float_constant_view) {
|
||||
if (write_float_constant_view_vertex) {
|
||||
++view_count_partial_update;
|
||||
}
|
||||
if (write_pixel_float_constant_view) {
|
||||
if (write_float_constant_view_pixel) {
|
||||
++view_count_partial_update;
|
||||
}
|
||||
if (write_bool_loop_constant_view) {
|
||||
|
@ -2011,15 +2036,15 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
if (write_fetch_constant_view) {
|
||||
++view_count_partial_update;
|
||||
}
|
||||
if (write_vertex_textures) {
|
||||
view_count_partial_update += vertex_texture_count;
|
||||
if (write_textures_vertex) {
|
||||
view_count_partial_update += texture_count_vertex;
|
||||
}
|
||||
if (write_pixel_textures) {
|
||||
view_count_partial_update += pixel_texture_count;
|
||||
if (write_textures_pixel) {
|
||||
view_count_partial_update += texture_count_pixel;
|
||||
}
|
||||
// All the constants + shared memory + textures.
|
||||
uint32_t view_count_full_update =
|
||||
6 + vertex_texture_count + pixel_texture_count;
|
||||
6 + texture_count_vertex + texture_count_pixel;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE view_cpu_handle;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE view_gpu_handle;
|
||||
uint32_t descriptor_size_view = provider->GetViewDescriptorSize();
|
||||
|
@ -2030,14 +2055,22 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
XELOGE("Failed to allocate view descriptors!");
|
||||
return false;
|
||||
}
|
||||
uint32_t sampler_count_partial_update = 0;
|
||||
if (write_samplers_vertex) {
|
||||
sampler_count_partial_update += sampler_count_vertex;
|
||||
}
|
||||
if (write_samplers_pixel) {
|
||||
sampler_count_partial_update += sampler_count_pixel;
|
||||
}
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE sampler_cpu_handle = {};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE sampler_gpu_handle = {};
|
||||
uint32_t descriptor_size_sampler = provider->GetSamplerDescriptorSize();
|
||||
uint64_t sampler_full_update_index = 0;
|
||||
if (sampler_count != 0) {
|
||||
if (sampler_count_vertex != 0 || sampler_count_pixel != 0) {
|
||||
sampler_full_update_index = RequestSamplerDescriptors(
|
||||
draw_sampler_full_update_, write_samplers ? sampler_count : 0,
|
||||
sampler_count, sampler_cpu_handle, sampler_gpu_handle);
|
||||
draw_sampler_full_update_, sampler_count_partial_update,
|
||||
sampler_count_vertex + sampler_count_pixel, sampler_cpu_handle,
|
||||
sampler_gpu_handle);
|
||||
if (sampler_full_update_index == 0) {
|
||||
XELOGE("Failed to allocate sampler descriptors!");
|
||||
return false;
|
||||
|
@ -2047,11 +2080,11 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
// Need to update all view descriptors.
|
||||
write_system_constant_view = true;
|
||||
write_fetch_constant_view = true;
|
||||
write_vertex_float_constant_view = true;
|
||||
write_pixel_float_constant_view = true;
|
||||
write_float_constant_view_vertex = true;
|
||||
write_float_constant_view_pixel = true;
|
||||
write_bool_loop_constant_view = true;
|
||||
write_vertex_textures = vertex_texture_count != 0;
|
||||
write_pixel_textures = pixel_texture_count != 0;
|
||||
write_textures_vertex = texture_count_vertex != 0;
|
||||
write_textures_pixel = texture_count_pixel != 0;
|
||||
texture_bindings_written_vertex_ = false;
|
||||
texture_bindings_written_pixel_ = false;
|
||||
// If updating fully, write the shared memory descriptor (t0).
|
||||
|
@ -2061,16 +2094,17 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
view_gpu_handle.ptr += descriptor_size_view;
|
||||
current_graphics_root_up_to_date_ &= ~(1u << kRootParameter_SharedMemory);
|
||||
}
|
||||
if (sampler_count != 0 &&
|
||||
draw_sampler_full_update_ != sampler_full_update_index) {
|
||||
write_samplers = true;
|
||||
if (draw_sampler_full_update_ != sampler_full_update_index) {
|
||||
write_samplers_vertex = sampler_count_vertex != 0;
|
||||
write_samplers_pixel = sampler_count_pixel != 0;
|
||||
samplers_written_vertex_ = false;
|
||||
samplers_written_pixel_ = false;
|
||||
}
|
||||
|
||||
// Write the descriptors.
|
||||
D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_desc;
|
||||
if (write_system_constant_view) {
|
||||
gpu_handle_system_constants_ = view_gpu_handle;
|
||||
// System constants.
|
||||
constant_buffer_desc.BufferLocation =
|
||||
cbuffer_bindings_system_.buffer_address;
|
||||
constant_buffer_desc.SizeInBytes =
|
||||
|
@ -2081,33 +2115,30 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
current_graphics_root_up_to_date_ &=
|
||||
~(1u << kRootParameter_SystemConstants);
|
||||
}
|
||||
if (write_vertex_float_constant_view) {
|
||||
gpu_handle_vertex_float_constants_ = view_gpu_handle;
|
||||
// Vertex float constants.
|
||||
if (write_float_constant_view_vertex) {
|
||||
gpu_handle_float_constants_vertex_ = view_gpu_handle;
|
||||
constant_buffer_desc.BufferLocation =
|
||||
cbuffer_bindings_vertex_float_.buffer_address;
|
||||
constant_buffer_desc.SizeInBytes = vertex_shader_float_constant_size;
|
||||
cbuffer_bindings_float_vertex_.buffer_address;
|
||||
constant_buffer_desc.SizeInBytes = float_constant_size_vertex;
|
||||
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);
|
||||
~(1u << kRootParameter_FloatConstantsVertex);
|
||||
}
|
||||
if (write_pixel_float_constant_view) {
|
||||
gpu_handle_pixel_float_constants_ = view_gpu_handle;
|
||||
// Pixel float constants.
|
||||
if (write_float_constant_view_pixel) {
|
||||
gpu_handle_float_constants_pixel_ = view_gpu_handle;
|
||||
constant_buffer_desc.BufferLocation =
|
||||
cbuffer_bindings_pixel_float_.buffer_address;
|
||||
constant_buffer_desc.SizeInBytes = pixel_shader_float_constant_size;
|
||||
cbuffer_bindings_float_pixel_.buffer_address;
|
||||
constant_buffer_desc.SizeInBytes = float_constant_size_pixel;
|
||||
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);
|
||||
~(1u << kRootParameter_FloatConstantsPixel);
|
||||
}
|
||||
if (write_bool_loop_constant_view) {
|
||||
gpu_handle_bool_loop_constants_ = view_gpu_handle;
|
||||
// Bool/loop constants.
|
||||
constant_buffer_desc.BufferLocation =
|
||||
cbuffer_bindings_bool_loop_.buffer_address;
|
||||
constant_buffer_desc.SizeInBytes = 768;
|
||||
|
@ -2119,7 +2150,6 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
}
|
||||
if (write_fetch_constant_view) {
|
||||
gpu_handle_fetch_constants_ = view_gpu_handle;
|
||||
// Fetch constants.
|
||||
constant_buffer_desc.BufferLocation =
|
||||
cbuffer_bindings_fetch_.buffer_address;
|
||||
constant_buffer_desc.SizeInBytes = 768;
|
||||
|
@ -2128,69 +2158,69 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
view_gpu_handle.ptr += descriptor_size_view;
|
||||
current_graphics_root_up_to_date_ &= ~(1u << kRootParameter_FetchConstants);
|
||||
}
|
||||
if (write_pixel_textures) {
|
||||
assert_true(current_graphics_root_extras_.pixel_textures !=
|
||||
if (write_textures_vertex) {
|
||||
assert_true(current_graphics_root_extras_.textures_vertex !=
|
||||
RootExtraParameterIndices::kUnavailable);
|
||||
gpu_handle_pixel_textures_ = view_gpu_handle;
|
||||
for (uint32_t i = 0; i < pixel_texture_count; ++i) {
|
||||
const D3D12Shader::TextureSRV& srv = pixel_textures[i];
|
||||
texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension,
|
||||
view_cpu_handle);
|
||||
view_cpu_handle.ptr += descriptor_size_view;
|
||||
view_gpu_handle.ptr += descriptor_size_view;
|
||||
}
|
||||
texture_bindings_written_pixel_ = true;
|
||||
texture_bindings_hash_pixel_ = new_pixel_texture_bindings_hash;
|
||||
current_graphics_root_up_to_date_ &=
|
||||
~(1u << current_graphics_root_extras_.pixel_textures);
|
||||
}
|
||||
if (write_vertex_textures) {
|
||||
assert_true(current_graphics_root_extras_.vertex_textures !=
|
||||
RootExtraParameterIndices::kUnavailable);
|
||||
gpu_handle_vertex_textures_ = view_gpu_handle;
|
||||
for (uint32_t i = 0; i < vertex_texture_count; ++i) {
|
||||
const D3D12Shader::TextureSRV& srv = vertex_textures[i];
|
||||
gpu_handle_textures_vertex_ = view_gpu_handle;
|
||||
for (uint32_t i = 0; i < texture_count_vertex; ++i) {
|
||||
const D3D12Shader::TextureSRV& srv = textures_vertex[i];
|
||||
texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension,
|
||||
view_cpu_handle);
|
||||
view_cpu_handle.ptr += descriptor_size_view;
|
||||
view_gpu_handle.ptr += descriptor_size_view;
|
||||
}
|
||||
texture_bindings_written_vertex_ = true;
|
||||
texture_bindings_hash_vertex_ = new_vertex_texture_bindings_hash;
|
||||
current_texture_bindings_hash_vertex_ = texture_bindings_hash_vertex;
|
||||
current_graphics_root_up_to_date_ &=
|
||||
~(1u << current_graphics_root_extras_.vertex_textures);
|
||||
~(1u << current_graphics_root_extras_.textures_vertex);
|
||||
}
|
||||
if (write_samplers) {
|
||||
if (pixel_sampler_count != 0) {
|
||||
assert_true(current_graphics_root_extras_.pixel_samplers !=
|
||||
RootExtraParameterIndices::kUnavailable);
|
||||
gpu_handle_pixel_samplers_ = sampler_gpu_handle;
|
||||
for (uint32_t i = 0; i < pixel_sampler_count; ++i) {
|
||||
const D3D12Shader::SamplerBinding& sampler = pixel_samplers[i];
|
||||
texture_cache_->WriteSampler(sampler.fetch_constant, sampler.mag_filter,
|
||||
sampler.min_filter, sampler.mip_filter,
|
||||
sampler.aniso_filter, sampler_cpu_handle);
|
||||
sampler_cpu_handle.ptr += descriptor_size_sampler;
|
||||
sampler_gpu_handle.ptr += descriptor_size_sampler;
|
||||
}
|
||||
current_graphics_root_up_to_date_ &=
|
||||
~(1u << current_graphics_root_extras_.pixel_samplers);
|
||||
if (write_textures_pixel) {
|
||||
assert_true(current_graphics_root_extras_.textures_pixel !=
|
||||
RootExtraParameterIndices::kUnavailable);
|
||||
gpu_handle_textures_pixel_ = view_gpu_handle;
|
||||
for (uint32_t i = 0; i < texture_count_pixel; ++i) {
|
||||
const D3D12Shader::TextureSRV& srv = textures_pixel[i];
|
||||
texture_cache_->WriteTextureSRV(srv.fetch_constant, srv.dimension,
|
||||
view_cpu_handle);
|
||||
view_cpu_handle.ptr += descriptor_size_view;
|
||||
view_gpu_handle.ptr += descriptor_size_view;
|
||||
}
|
||||
if (vertex_sampler_count != 0) {
|
||||
assert_true(current_graphics_root_extras_.vertex_samplers !=
|
||||
RootExtraParameterIndices::kUnavailable);
|
||||
gpu_handle_vertex_samplers_ = sampler_gpu_handle;
|
||||
for (uint32_t i = 0; i < vertex_sampler_count; ++i) {
|
||||
const D3D12Shader::SamplerBinding& sampler = vertex_samplers[i];
|
||||
texture_cache_->WriteSampler(sampler.fetch_constant, sampler.mag_filter,
|
||||
sampler.min_filter, sampler.mip_filter,
|
||||
sampler.aniso_filter, sampler_cpu_handle);
|
||||
sampler_cpu_handle.ptr += descriptor_size_sampler;
|
||||
sampler_gpu_handle.ptr += descriptor_size_sampler;
|
||||
}
|
||||
current_graphics_root_up_to_date_ &=
|
||||
~(1u << current_graphics_root_extras_.vertex_samplers);
|
||||
texture_bindings_written_pixel_ = true;
|
||||
current_texture_bindings_hash_pixel_ = texture_bindings_hash_pixel;
|
||||
current_graphics_root_up_to_date_ &=
|
||||
~(1u << current_graphics_root_extras_.textures_pixel);
|
||||
}
|
||||
if (write_samplers_vertex) {
|
||||
assert_true(current_graphics_root_extras_.samplers_vertex !=
|
||||
RootExtraParameterIndices::kUnavailable);
|
||||
gpu_handle_samplers_vertex_ = sampler_gpu_handle;
|
||||
for (uint32_t i = 0; i < sampler_count_vertex; ++i) {
|
||||
texture_cache_->WriteSampler(
|
||||
texture_cache_->GetSamplerParameters(samplers_vertex[i]),
|
||||
sampler_cpu_handle);
|
||||
sampler_cpu_handle.ptr += descriptor_size_sampler;
|
||||
sampler_gpu_handle.ptr += descriptor_size_sampler;
|
||||
}
|
||||
samplers_written_vertex_ = true;
|
||||
current_samplers_hash_vertex_ = samplers_hash_vertex;
|
||||
current_graphics_root_up_to_date_ &=
|
||||
~(1u << current_graphics_root_extras_.samplers_vertex);
|
||||
}
|
||||
if (write_samplers_pixel) {
|
||||
assert_true(current_graphics_root_extras_.samplers_pixel !=
|
||||
RootExtraParameterIndices::kUnavailable);
|
||||
gpu_handle_samplers_pixel_ = sampler_gpu_handle;
|
||||
for (uint32_t i = 0; i < sampler_count_pixel; ++i) {
|
||||
texture_cache_->WriteSampler(
|
||||
texture_cache_->GetSamplerParameters(samplers_pixel[i]),
|
||||
sampler_cpu_handle);
|
||||
sampler_cpu_handle.ptr += descriptor_size_sampler;
|
||||
sampler_gpu_handle.ptr += descriptor_size_sampler;
|
||||
}
|
||||
samplers_written_pixel_ = true;
|
||||
current_samplers_hash_pixel_ = samplers_hash_pixel;
|
||||
current_graphics_root_up_to_date_ &=
|
||||
~(1u << current_graphics_root_extras_.samplers_pixel);
|
||||
}
|
||||
|
||||
// Wrote new descriptors on the current page.
|
||||
|
@ -2205,19 +2235,19 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
current_graphics_root_up_to_date_ |= 1u << kRootParameter_FetchConstants;
|
||||
}
|
||||
if (!(current_graphics_root_up_to_date_ &
|
||||
(1u << kRootParameter_VertexFloatConstants))) {
|
||||
(1u << kRootParameter_FloatConstantsVertex))) {
|
||||
command_list->SetGraphicsRootDescriptorTable(
|
||||
kRootParameter_VertexFloatConstants,
|
||||
gpu_handle_vertex_float_constants_);
|
||||
kRootParameter_FloatConstantsVertex,
|
||||
gpu_handle_float_constants_vertex_);
|
||||
current_graphics_root_up_to_date_ |= 1u
|
||||
<< kRootParameter_VertexFloatConstants;
|
||||
<< kRootParameter_FloatConstantsVertex;
|
||||
}
|
||||
if (!(current_graphics_root_up_to_date_ &
|
||||
(1u << kRootParameter_PixelFloatConstants))) {
|
||||
(1u << kRootParameter_FloatConstantsPixel))) {
|
||||
command_list->SetGraphicsRootDescriptorTable(
|
||||
kRootParameter_PixelFloatConstants, gpu_handle_pixel_float_constants_);
|
||||
kRootParameter_FloatConstantsPixel, gpu_handle_float_constants_pixel_);
|
||||
current_graphics_root_up_to_date_ |= 1u
|
||||
<< kRootParameter_PixelFloatConstants;
|
||||
<< kRootParameter_FloatConstantsPixel;
|
||||
}
|
||||
if (!(current_graphics_root_up_to_date_ &
|
||||
(1u << kRootParameter_SystemConstants))) {
|
||||
|
@ -2238,32 +2268,32 @@ bool D3D12CommandProcessor::UpdateBindings(
|
|||
current_graphics_root_up_to_date_ |= 1u << kRootParameter_SharedMemory;
|
||||
}
|
||||
uint32_t extra_index;
|
||||
extra_index = current_graphics_root_extras_.pixel_textures;
|
||||
extra_index = current_graphics_root_extras_.textures_pixel;
|
||||
if (extra_index != RootExtraParameterIndices::kUnavailable &&
|
||||
!(current_graphics_root_up_to_date_ & (1u << extra_index))) {
|
||||
command_list->SetGraphicsRootDescriptorTable(extra_index,
|
||||
gpu_handle_pixel_textures_);
|
||||
gpu_handle_textures_pixel_);
|
||||
current_graphics_root_up_to_date_ |= 1u << extra_index;
|
||||
}
|
||||
extra_index = current_graphics_root_extras_.pixel_samplers;
|
||||
extra_index = current_graphics_root_extras_.samplers_pixel;
|
||||
if (extra_index != RootExtraParameterIndices::kUnavailable &&
|
||||
!(current_graphics_root_up_to_date_ & (1u << extra_index))) {
|
||||
command_list->SetGraphicsRootDescriptorTable(extra_index,
|
||||
gpu_handle_pixel_samplers_);
|
||||
gpu_handle_samplers_pixel_);
|
||||
current_graphics_root_up_to_date_ |= 1u << extra_index;
|
||||
}
|
||||
extra_index = current_graphics_root_extras_.vertex_textures;
|
||||
extra_index = current_graphics_root_extras_.textures_vertex;
|
||||
if (extra_index != RootExtraParameterIndices::kUnavailable &&
|
||||
!(current_graphics_root_up_to_date_ & (1u << extra_index))) {
|
||||
command_list->SetGraphicsRootDescriptorTable(extra_index,
|
||||
gpu_handle_vertex_textures_);
|
||||
gpu_handle_textures_vertex_);
|
||||
current_graphics_root_up_to_date_ |= 1u << extra_index;
|
||||
}
|
||||
extra_index = current_graphics_root_extras_.vertex_samplers;
|
||||
extra_index = current_graphics_root_extras_.samplers_vertex;
|
||||
if (extra_index != RootExtraParameterIndices::kUnavailable &&
|
||||
!(current_graphics_root_up_to_date_ & (1u << extra_index))) {
|
||||
command_list->SetGraphicsRootDescriptorTable(extra_index,
|
||||
gpu_handle_vertex_samplers_);
|
||||
gpu_handle_samplers_vertex_);
|
||||
current_graphics_root_up_to_date_ |= 1u << extra_index;
|
||||
}
|
||||
|
||||
|
|
|
@ -146,9 +146,9 @@ class D3D12CommandProcessor : public CommandProcessor {
|
|||
kRootParameter_FetchConstants,
|
||||
// Quite frequently changed (for one object drawn multiple times, for
|
||||
// instance - may contain projection matrices).
|
||||
kRootParameter_VertexFloatConstants,
|
||||
kRootParameter_FloatConstantsVertex,
|
||||
// Less frequently changed (per-material).
|
||||
kRootParameter_PixelFloatConstants,
|
||||
kRootParameter_FloatConstantsPixel,
|
||||
// Rarely changed - system constants like viewport and alpha testing.
|
||||
kRootParameter_SystemConstants,
|
||||
// Pretty rarely used and rarely changed - flow control constants.
|
||||
|
@ -169,10 +169,10 @@ class D3D12CommandProcessor : public CommandProcessor {
|
|||
};
|
||||
|
||||
struct RootExtraParameterIndices {
|
||||
uint32_t pixel_textures;
|
||||
uint32_t pixel_samplers;
|
||||
uint32_t vertex_textures;
|
||||
uint32_t vertex_samplers;
|
||||
uint32_t textures_pixel;
|
||||
uint32_t samplers_pixel;
|
||||
uint32_t textures_vertex;
|
||||
uint32_t samplers_vertex;
|
||||
static constexpr uint32_t kUnavailable = UINT32_MAX;
|
||||
};
|
||||
// Gets the indices of optional root parameters. Returns the total parameter
|
||||
|
@ -283,8 +283,8 @@ class D3D12CommandProcessor : public CommandProcessor {
|
|||
DxbcShaderTranslator::SystemConstants system_constants_;
|
||||
|
||||
// Float constant usage masks of the last draw call.
|
||||
uint64_t float_constant_map_vertex_[4];
|
||||
uint64_t float_constant_map_pixel_[4];
|
||||
uint64_t current_float_constant_map_vertex_[4];
|
||||
uint64_t current_float_constant_map_pixel_[4];
|
||||
|
||||
// Constant buffer bindings.
|
||||
struct ConstantBufferBinding {
|
||||
|
@ -292,8 +292,8 @@ class D3D12CommandProcessor : public CommandProcessor {
|
|||
bool up_to_date;
|
||||
};
|
||||
ConstantBufferBinding cbuffer_bindings_system_;
|
||||
ConstantBufferBinding cbuffer_bindings_vertex_float_;
|
||||
ConstantBufferBinding cbuffer_bindings_pixel_float_;
|
||||
ConstantBufferBinding cbuffer_bindings_float_vertex_;
|
||||
ConstantBufferBinding cbuffer_bindings_float_pixel_;
|
||||
ConstantBufferBinding cbuffer_bindings_bool_loop_;
|
||||
ConstantBufferBinding cbuffer_bindings_fetch_;
|
||||
|
||||
|
@ -308,20 +308,30 @@ class D3D12CommandProcessor : public CommandProcessor {
|
|||
// Hashes of the last texture bindings written to the current view descriptor
|
||||
// heap with the last used descriptor layout. Valid only when the
|
||||
// corresponding "written" variables are true.
|
||||
uint64_t texture_bindings_hash_vertex_;
|
||||
uint64_t texture_bindings_hash_pixel_;
|
||||
uint64_t current_texture_bindings_hash_vertex_;
|
||||
uint64_t current_texture_bindings_hash_pixel_;
|
||||
|
||||
// Whether the last used samplers have been written to the current sampler
|
||||
// descriptor heap.
|
||||
bool samplers_written_vertex_;
|
||||
bool samplers_written_pixel_;
|
||||
// Hashes of the last sampler parameters written to the current sampler
|
||||
// descriptor heap with the last used descriptor layout. Valid only when the
|
||||
// corresponding "written" variables are true.
|
||||
uint64_t current_samplers_hash_vertex_;
|
||||
uint64_t current_samplers_hash_pixel_;
|
||||
|
||||
// Latest descriptor handles used for handling Xenos draw calls.
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_system_constants_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_vertex_float_constants_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_pixel_float_constants_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_float_constants_vertex_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_float_constants_pixel_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_bool_loop_constants_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_fetch_constants_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_shared_memory_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_pixel_textures_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_pixel_samplers_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_vertex_textures_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_vertex_samplers_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_textures_vertex_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_textures_pixel_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_samplers_vertex_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_samplers_pixel_;
|
||||
|
||||
// Current primitive topology.
|
||||
D3D_PRIMITIVE_TOPOLOGY primitive_topology_;
|
||||
|
|
|
@ -576,41 +576,82 @@ void TextureCache::WriteTextureSRV(uint32_t fetch_constant,
|
|||
device->CreateShaderResourceView(resource, &desc, handle);
|
||||
}
|
||||
|
||||
void TextureCache::WriteSampler(uint32_t fetch_constant,
|
||||
TextureFilter mag_filter,
|
||||
TextureFilter min_filter,
|
||||
TextureFilter mip_filter,
|
||||
AnisoFilter aniso_filter,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle) {
|
||||
TextureCache::SamplerParameters TextureCache::GetSamplerParameters(
|
||||
const D3D12Shader::SamplerBinding& binding) const {
|
||||
auto& regs = *register_file_;
|
||||
uint32_t r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + fetch_constant * 6;
|
||||
uint32_t r =
|
||||
XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + binding.fetch_constant * 6;
|
||||
auto group =
|
||||
reinterpret_cast<const xenos::xe_gpu_fetch_group_t*>(®s.values[r]);
|
||||
auto& fetch = group->texture_fetch;
|
||||
if (mag_filter == TextureFilter::kUseFetchConst) {
|
||||
mag_filter = TextureFilter(fetch.mag_filter);
|
||||
|
||||
SamplerParameters parameters;
|
||||
|
||||
parameters.clamp_x = ClampMode(fetch.clamp_x);
|
||||
parameters.clamp_y = ClampMode(fetch.clamp_y);
|
||||
parameters.clamp_z = ClampMode(fetch.clamp_z);
|
||||
parameters.border_color = BorderColor(fetch.border_color);
|
||||
|
||||
uint32_t mip_min_level = fetch.mip_min_level;
|
||||
uint32_t mip_max_level = fetch.mip_max_level;
|
||||
uint32_t base_page = fetch.base_address & 0x1FFFF;
|
||||
uint32_t mip_page = fetch.mip_address & 0x1FFFF;
|
||||
if (base_page == 0 || base_page == mip_page) {
|
||||
// Games should clamp mip level in this case anyway, but just for safety.
|
||||
mip_min_level = std::max(mip_min_level, 1u);
|
||||
}
|
||||
if (min_filter == TextureFilter::kUseFetchConst) {
|
||||
min_filter = TextureFilter(fetch.min_filter);
|
||||
if (mip_page == 0) {
|
||||
mip_max_level = 0;
|
||||
}
|
||||
if (mip_filter == TextureFilter::kUseFetchConst) {
|
||||
mip_filter = TextureFilter(fetch.mip_filter);
|
||||
}
|
||||
if (aniso_filter == AnisoFilter::kUseFetchConst) {
|
||||
aniso_filter = AnisoFilter(fetch.aniso_filter);
|
||||
}
|
||||
D3D12_SAMPLER_DESC desc;
|
||||
parameters.mip_min_level = mip_min_level;
|
||||
parameters.mip_max_level = std::max(mip_max_level, mip_min_level);
|
||||
parameters.lod_bias = fetch.lod_bias;
|
||||
|
||||
AnisoFilter aniso_filter = binding.aniso_filter == AnisoFilter::kUseFetchConst
|
||||
? AnisoFilter(fetch.aniso_filter)
|
||||
: binding.aniso_filter;
|
||||
aniso_filter = std::min(aniso_filter, AnisoFilter::kMax_16_1);
|
||||
parameters.aniso_filter = aniso_filter;
|
||||
if (aniso_filter != AnisoFilter::kDisabled) {
|
||||
desc.Filter = D3D12_FILTER_ANISOTROPIC;
|
||||
desc.MaxAnisotropy = std::min(1u << (uint32_t(aniso_filter) - 1), 16u);
|
||||
parameters.mag_linear = 1;
|
||||
parameters.min_linear = 1;
|
||||
parameters.mip_linear = 1;
|
||||
} else {
|
||||
D3D12_FILTER_TYPE d3d_filter_min = min_filter == TextureFilter::kLinear
|
||||
TextureFilter mag_filter =
|
||||
binding.mag_filter == TextureFilter::kUseFetchConst
|
||||
? TextureFilter(fetch.mag_filter)
|
||||
: binding.mag_filter;
|
||||
parameters.mag_linear = mag_filter == TextureFilter::kLinear;
|
||||
TextureFilter min_filter =
|
||||
binding.min_filter == TextureFilter::kUseFetchConst
|
||||
? TextureFilter(fetch.min_filter)
|
||||
: binding.min_filter;
|
||||
parameters.min_linear = min_filter == TextureFilter::kLinear;
|
||||
TextureFilter mip_filter =
|
||||
binding.mip_filter == TextureFilter::kUseFetchConst
|
||||
? TextureFilter(fetch.mip_filter)
|
||||
: binding.mip_filter;
|
||||
parameters.mip_linear = mip_filter == TextureFilter::kLinear;
|
||||
// TODO(Triang3l): Investigate mip_filter TextureFilter::kBaseMap.
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
void TextureCache::WriteSampler(SamplerParameters parameters,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle) const {
|
||||
D3D12_SAMPLER_DESC desc;
|
||||
if (parameters.aniso_filter != AnisoFilter::kDisabled) {
|
||||
desc.Filter = D3D12_FILTER_ANISOTROPIC;
|
||||
desc.MaxAnisotropy = 1u << (uint32_t(parameters.aniso_filter) - 1);
|
||||
} else {
|
||||
D3D12_FILTER_TYPE d3d_filter_min = parameters.min_linear
|
||||
? D3D12_FILTER_TYPE_LINEAR
|
||||
: D3D12_FILTER_TYPE_POINT;
|
||||
D3D12_FILTER_TYPE d3d_filter_mag = mag_filter == TextureFilter::kLinear
|
||||
D3D12_FILTER_TYPE d3d_filter_mag = parameters.mag_linear
|
||||
? D3D12_FILTER_TYPE_LINEAR
|
||||
: D3D12_FILTER_TYPE_POINT;
|
||||
D3D12_FILTER_TYPE d3d_filter_mip = mip_filter == TextureFilter::kLinear
|
||||
D3D12_FILTER_TYPE d3d_filter_mip = parameters.mip_linear
|
||||
? D3D12_FILTER_TYPE_LINEAR
|
||||
: D3D12_FILTER_TYPE_POINT;
|
||||
// TODO(Triang3l): Investigate mip_filter TextureFilter::kBaseMap.
|
||||
|
@ -630,13 +671,13 @@ void TextureCache::WriteSampler(uint32_t fetch_constant,
|
|||
/* kClampToBorder */ D3D12_TEXTURE_ADDRESS_MODE_BORDER,
|
||||
/* kMirrorClampToBorder */ D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE,
|
||||
};
|
||||
desc.AddressU = kAddressModeMap[fetch.clamp_x];
|
||||
desc.AddressV = kAddressModeMap[fetch.clamp_y];
|
||||
desc.AddressW = kAddressModeMap[fetch.clamp_z];
|
||||
desc.MipLODBias = fetch.lod_bias * (1.0f / 32.0f);
|
||||
desc.AddressU = kAddressModeMap[uint32_t(parameters.clamp_x)];
|
||||
desc.AddressV = kAddressModeMap[uint32_t(parameters.clamp_y)];
|
||||
desc.AddressW = kAddressModeMap[uint32_t(parameters.clamp_z)];
|
||||
desc.MipLODBias = parameters.lod_bias * (1.0f / 32.0f);
|
||||
desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
|
||||
// TODO(Triang3l): Border colors k_ACBYCR_BLACK and k_ACBCRY_BLACK.
|
||||
if (BorderColor(fetch.border_color) == BorderColor::k_AGBR_White) {
|
||||
if (parameters.border_color == BorderColor::k_AGBR_White) {
|
||||
desc.BorderColor[0] = 1.0f;
|
||||
desc.BorderColor[1] = 1.0f;
|
||||
desc.BorderColor[2] = 1.0f;
|
||||
|
@ -647,18 +688,8 @@ void TextureCache::WriteSampler(uint32_t fetch_constant,
|
|||
desc.BorderColor[2] = 0.0f;
|
||||
desc.BorderColor[3] = 0.0f;
|
||||
}
|
||||
desc.MinLOD = float(fetch.mip_min_level);
|
||||
desc.MaxLOD = float(fetch.mip_max_level);
|
||||
uint32_t base_page = fetch.base_address & 0x1FFFF;
|
||||
uint32_t mip_page = fetch.mip_address & 0x1FFFF;
|
||||
if (base_page == 0 || base_page == mip_page) {
|
||||
// Games should clamp mip level in this case anyway, but just for safety.
|
||||
desc.MinLOD = std::max(desc.MinLOD, 1.0f);
|
||||
}
|
||||
if (mip_page == 0) {
|
||||
desc.MaxLOD = 0.0f;
|
||||
}
|
||||
desc.MaxLOD = std::max(desc.MaxLOD, desc.MinLOD);
|
||||
desc.MinLOD = float(parameters.mip_min_level);
|
||||
desc.MaxLOD = float(parameters.mip_max_level);
|
||||
auto device =
|
||||
command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice();
|
||||
device->CreateSampler(&desc, handle);
|
||||
|
|
|
@ -55,6 +55,42 @@ class D3D12CommandProcessor;
|
|||
// this way anyway.
|
||||
class TextureCache {
|
||||
public:
|
||||
// Sampler parameters that can be directly converted to a host sampler or used
|
||||
// for binding hashing.
|
||||
union SamplerParameters {
|
||||
struct {
|
||||
ClampMode clamp_x : 3; // 3
|
||||
ClampMode clamp_y : 3; // 6
|
||||
ClampMode clamp_z : 3; // 9
|
||||
BorderColor border_color : 2; // 11
|
||||
// For anisotropic, these are true.
|
||||
uint32_t mag_linear : 1; // 12
|
||||
uint32_t min_linear : 1; // 13
|
||||
uint32_t mip_linear : 1; // 14
|
||||
AnisoFilter aniso_filter : 3; // 17
|
||||
uint32_t mip_min_level : 4; // 21
|
||||
uint32_t mip_max_level : 4; // 25
|
||||
|
||||
int32_t lod_bias : 10; // 42
|
||||
};
|
||||
uint64_t value;
|
||||
|
||||
// Clearing the unused bits.
|
||||
SamplerParameters() : value(0) {}
|
||||
SamplerParameters(const SamplerParameters& parameters)
|
||||
: value(parameters.value) {}
|
||||
SamplerParameters& operator=(const SamplerParameters& parameters) {
|
||||
value = parameters.value;
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const SamplerParameters& parameters) const {
|
||||
return value == parameters.value;
|
||||
}
|
||||
bool operator!=(const SamplerParameters& parameters) const {
|
||||
return value != parameters.value;
|
||||
}
|
||||
};
|
||||
|
||||
TextureCache(D3D12CommandProcessor* command_processor,
|
||||
RegisterFile* register_file, SharedMemory* shared_memory);
|
||||
~TextureCache();
|
||||
|
@ -84,10 +120,11 @@ class TextureCache {
|
|||
void WriteTextureSRV(uint32_t fetch_constant,
|
||||
TextureDimension shader_dimension,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle);
|
||||
void WriteSampler(uint32_t fetch_constant, TextureFilter mag_filter,
|
||||
TextureFilter min_filter, TextureFilter mip_filter,
|
||||
AnisoFilter aniso_filter,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle);
|
||||
|
||||
SamplerParameters GetSamplerParameters(
|
||||
const D3D12Shader::SamplerBinding& binding) const;
|
||||
void WriteSampler(SamplerParameters parameters,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle) const;
|
||||
|
||||
static inline DXGI_FORMAT GetResolveDXGIFormat(TextureFormat format) {
|
||||
return host_formats_[uint32_t(format)].dxgi_format_resolve_tile;
|
||||
|
|
Loading…
Reference in New Issue