Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental

This commit is contained in:
Gliniak
2022-07-21 18:52:33 +02:00
25 changed files with 3393 additions and 3255 deletions

View File

@@ -2163,12 +2163,21 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
draw_util::GetNormalizedDepthControl(regs);
// Shader modifications.
uint32_t ps_param_gen_pos = UINT32_MAX;
uint32_t interpolator_mask =
pixel_shader ? (vertex_shader->writes_interpolators() &
pixel_shader->GetInterpolatorInputMask(
regs.Get<reg::SQ_PROGRAM_CNTL>(),
regs.Get<reg::SQ_CONTEXT_MISC>(), ps_param_gen_pos))
: 0;
DxbcShaderTranslator::Modification vertex_shader_modification =
pipeline_cache_->GetCurrentVertexShaderModification(
*vertex_shader, primitive_processing_result.host_vertex_shader_type);
*vertex_shader, primitive_processing_result.host_vertex_shader_type,
interpolator_mask);
DxbcShaderTranslator::Modification pixel_shader_modification =
pixel_shader ? pipeline_cache_->GetCurrentPixelShaderModification(
*pixel_shader, normalized_depth_control)
*pixel_shader, interpolator_mask, ps_param_gen_pos,
normalized_depth_control)
: DxbcShaderTranslator::Modification(0);
// Set up the render targets - this may perform dispatches and draws.
@@ -3234,25 +3243,14 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
if (pa_cl_vte_cntl.vtx_w0_fmt) {
flags |= DxbcShaderTranslator::kSysFlag_WNotReciprocal;
}
// User clip planes (UCP_ENA_#), when not CLIP_DISABLE.
if (!pa_cl_clip_cntl.clip_disable) {
flags |= (pa_cl_clip_cntl.value & 0b111111)
<< DxbcShaderTranslator::kSysFlag_UserClipPlane0_Shift;
}
// Whether the primitive is polygonal and SV_IsFrontFace matters.
if (primitive_polygonal) {
flags |= DxbcShaderTranslator::kSysFlag_PrimitivePolygonal;
}
// Primitive type.
if (vgt_draw_initiator.prim_type == xenos::PrimitiveType::kPointList) {
flags |= DxbcShaderTranslator::kSysFlag_PrimitivePoint;
} else if (draw_util::IsPrimitiveLine(regs)) {
if (draw_util::IsPrimitiveLine(regs)) {
flags |= DxbcShaderTranslator::kSysFlag_PrimitiveLine;
}
// Primitive killing condition.
if (pa_cl_clip_cntl.vtx_kill_or) {
flags |= DxbcShaderTranslator::kSysFlag_KillIfAnyVertexKilled;
}
// Depth format.
if (rb_depth_info.depth_format == xenos::DepthRenderTargetFormat::kD24FS8) {
flags |= DxbcShaderTranslator::kSysFlag_DepthFloat24;
@@ -3332,18 +3330,24 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
system_constants_.vertex_index_max = vgt_max_vtx_indx;
// User clip planes (UCP_ENA_#), when not CLIP_DISABLE.
// The shader knows only the total count - tightly packing the user clip
// planes that are actually used.
if (!pa_cl_clip_cntl.clip_disable) {
for (uint32_t i = 0; i < 6; ++i) {
if (!(pa_cl_clip_cntl.value & (1 << i))) {
continue;
}
const float* ucp = &regs[XE_GPU_REG_PA_CL_UCP_0_X + i * 4].f32;
if (std::memcmp(system_constants_.user_clip_planes[i], ucp,
float* user_clip_plane_write_ptr = system_constants_.user_clip_planes[0];
uint32_t user_clip_planes_remaining = pa_cl_clip_cntl.ucp_ena;
uint32_t user_clip_plane_index;
while (xe::bit_scan_forward(user_clip_planes_remaining,
&user_clip_plane_index)) {
user_clip_planes_remaining &= ~(UINT32_C(1) << user_clip_plane_index);
const float* user_clip_plane =
&regs[XE_GPU_REG_PA_CL_UCP_0_X + user_clip_plane_index * 4].f32;
if (std::memcmp(user_clip_plane_write_ptr, user_clip_plane,
4 * sizeof(float))) {
dirty = true;
std::memcpy(system_constants_.user_clip_planes[i], ucp,
std::memcpy(user_clip_plane_write_ptr, user_clip_plane,
4 * sizeof(float));
}
user_clip_plane_write_ptr += 4;
}
}
@@ -3394,22 +3398,6 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
system_constants_.point_screen_diameter_to_ndc_radius[1] =
point_screen_diameter_to_ndc_radius_y;
// Interpolator sampling pattern, centroid or center.
uint32_t interpolator_sampling_pattern =
xenos::GetInterpolatorSamplingPattern(
rb_surface_info.msaa_samples, sq_context_misc.sc_sample_cntl,
regs.Get<reg::SQ_INTERPOLATOR_CNTL>().sampling_pattern);
dirty |= system_constants_.interpolator_sampling_pattern !=
interpolator_sampling_pattern;
system_constants_.interpolator_sampling_pattern =
interpolator_sampling_pattern;
// Pixel parameter register.
uint32_t ps_param_gen =
sq_program_cntl.param_gen ? sq_context_misc.param_gen_pos : UINT_MAX;
dirty |= system_constants_.ps_param_gen != ps_param_gen;
system_constants_.ps_param_gen = ps_param_gen;
// Texture signedness / gamma.
bool gamma_render_target_as_srgb =
render_target_cache_->gamma_render_target_as_srgb();

View File

@@ -643,8 +643,13 @@ void PipelineCache::InitializeShaderStorage(
}
GeometryShaderKey pipeline_geometry_shader_key;
pipeline_runtime_description.geometry_shader =
GetGeometryShaderKey(pipeline_description.geometry_shader,
pipeline_geometry_shader_key)
GetGeometryShaderKey(
pipeline_description.geometry_shader,
DxbcShaderTranslator::Modification(
pipeline_description.vertex_shader_modification),
DxbcShaderTranslator::Modification(
pipeline_description.pixel_shader_modification),
pipeline_geometry_shader_key)
? &GetGeometryShader(pipeline_geometry_shader_key)
: nullptr;
pipeline_runtime_description.root_signature =
@@ -855,29 +860,71 @@ D3D12Shader* PipelineCache::LoadShader(xenos::ShaderType shader_type,
DxbcShaderTranslator::Modification
PipelineCache::GetCurrentVertexShaderModification(
const Shader& shader,
Shader::HostVertexShaderType host_vertex_shader_type) const {
const Shader& shader, Shader::HostVertexShaderType host_vertex_shader_type,
uint32_t interpolator_mask) const {
assert_true(shader.type() == xenos::ShaderType::kVertex);
assert_true(shader.is_ucode_analyzed());
const auto& regs = register_file_;
auto sq_program_cntl = regs.Get<reg::SQ_PROGRAM_CNTL>();
return DxbcShaderTranslator::Modification(
DxbcShaderTranslator::Modification modification(
shader_translator_->GetDefaultVertexShaderModification(
shader.GetDynamicAddressableRegisterCount(sq_program_cntl.vs_num_reg),
shader.GetDynamicAddressableRegisterCount(
regs.Get<reg::SQ_PROGRAM_CNTL>().vs_num_reg),
host_vertex_shader_type));
modification.vertex.interpolator_mask = interpolator_mask;
auto pa_cl_clip_cntl = regs.Get<reg::PA_CL_CLIP_CNTL>();
uint32_t user_clip_planes =
pa_cl_clip_cntl.clip_disable ? 0 : pa_cl_clip_cntl.ucp_ena;
modification.vertex.user_clip_plane_count = xe::bit_count(user_clip_planes);
modification.vertex.user_clip_plane_cull =
uint32_t(user_clip_planes && pa_cl_clip_cntl.ucp_cull_only_ena);
modification.vertex.vertex_kill_and =
uint32_t((shader.writes_point_size_edge_flag_kill_vertex() & 0b100) &&
!pa_cl_clip_cntl.vtx_kill_or);
modification.vertex.output_point_size =
uint32_t((shader.writes_point_size_edge_flag_kill_vertex() & 0b001) &&
regs.Get<reg::VGT_DRAW_INITIATOR>().prim_type ==
xenos::PrimitiveType::kPointList);
return modification;
}
DxbcShaderTranslator::Modification
PipelineCache::GetCurrentPixelShaderModification(
const Shader& shader, reg::RB_DEPTHCONTROL normalized_depth_control) const {
const Shader& shader, uint32_t interpolator_mask, uint32_t param_gen_pos,
reg::RB_DEPTHCONTROL normalized_depth_control) const {
assert_true(shader.type() == xenos::ShaderType::kPixel);
assert_true(shader.is_ucode_analyzed());
const auto& regs = register_file_;
auto sq_program_cntl = regs.Get<reg::SQ_PROGRAM_CNTL>();
DxbcShaderTranslator::Modification modification(
shader_translator_->GetDefaultPixelShaderModification(
shader.GetDynamicAddressableRegisterCount(
sq_program_cntl.ps_num_reg)));
regs.Get<reg::SQ_PROGRAM_CNTL>().ps_num_reg)));
modification.pixel.interpolator_mask = interpolator_mask;
modification.pixel.interpolators_centroid =
interpolator_mask &
~xenos::GetInterpolatorSamplingPattern(
regs.Get<reg::RB_SURFACE_INFO>().msaa_samples,
regs.Get<reg::SQ_CONTEXT_MISC>().sc_sample_cntl,
regs.Get<reg::SQ_INTERPOLATOR_CNTL>().sampling_pattern);
if (param_gen_pos < xenos::kMaxInterpolators) {
modification.pixel.param_gen_enable = 1;
modification.pixel.param_gen_interpolator = param_gen_pos;
modification.pixel.param_gen_point =
uint32_t(regs.Get<reg::VGT_DRAW_INITIATOR>().prim_type ==
xenos::PrimitiveType::kPointList);
} else {
modification.pixel.param_gen_enable = 0;
modification.pixel.param_gen_interpolator = 0;
modification.pixel.param_gen_point = 0;
}
if (render_target_cache_.GetPath() ==
RenderTargetCache::Path::kHostRenderTargets) {
using DepthStencilMode =
@@ -901,6 +948,7 @@ PipelineCache::GetCurrentPixelShaderModification(
}
}
}
return modification;
}
@@ -1086,6 +1134,8 @@ bool PipelineCache::TranslateAnalyzedShader(
host_shader_type = "patch-indexed quad domain";
break;
default:
assert(modification.vertex.host_vertex_shader_type ==
Shader::HostVertexShaderType::kVertex);
host_shader_type = "vertex";
}
} else {
@@ -1356,7 +1406,12 @@ bool PipelineCache::GetCurrentStateDescription(
}
GeometryShaderKey geometry_shader_key;
runtime_description_out.geometry_shader =
GetGeometryShaderKey(description_out.geometry_shader, geometry_shader_key)
GetGeometryShaderKey(
description_out.geometry_shader,
DxbcShaderTranslator::Modification(vertex_shader->modification()),
DxbcShaderTranslator::Modification(
pixel_shader ? pixel_shader->modification() : 0),
geometry_shader_key)
? &GetGeometryShader(geometry_shader_key)
: nullptr;
@@ -1631,20 +1686,26 @@ bool PipelineCache::GetCurrentStateDescription(
}
bool PipelineCache::GetGeometryShaderKey(
PipelineGeometryShader geometry_shader_type, GeometryShaderKey& key_out) {
PipelineGeometryShader geometry_shader_type,
DxbcShaderTranslator::Modification vertex_shader_modification,
DxbcShaderTranslator::Modification pixel_shader_modification,
GeometryShaderKey& key_out) {
if (geometry_shader_type == PipelineGeometryShader::kNone) {
return false;
}
assert_true(vertex_shader_modification.vertex.interpolator_mask ==
pixel_shader_modification.pixel.interpolator_mask);
GeometryShaderKey key;
key.type = geometry_shader_type;
// TODO(Triang3l): Make the linkage parameters depend on the real needs of the
// vertex and the pixel shader.
key.interpolator_count = xenos::kMaxInterpolators;
key.user_clip_plane_count = 6;
key.user_clip_plane_cull = 0;
key.has_vertex_kill_and = 1;
key.has_point_size = 1;
key.has_point_coordinates = 1;
key.interpolator_count =
xe::bit_count(vertex_shader_modification.vertex.interpolator_mask);
key.user_clip_plane_count =
vertex_shader_modification.vertex.user_clip_plane_count;
key.user_clip_plane_cull =
vertex_shader_modification.vertex.user_clip_plane_cull;
key.has_vertex_kill_and = vertex_shader_modification.vertex.vertex_kill_and;
key.has_point_size = vertex_shader_modification.vertex.output_point_size;
key.has_point_coordinates = pixel_shader_modification.pixel.param_gen_point;
key_out = key;
return true;
}
@@ -1886,16 +1947,15 @@ void PipelineCache::CreateDxbcGeometryShader(
uint32_t input_clip_and_cull_distance_count =
input_clip_distance_count + input_cull_distance_count;
// Interpolators, point size, position, clip and cull distances (parameters
// containing only clip or cull distances, and also one parameter containing
// both if present).
// TODO(Triang3l): Reorder as needed when the respective changes are done in
// the shader translator.
// Interpolators, position, clip and cull distances (parameters containing
// only clip or cull distances, and also one parameter containing both if
// present), point size.
uint32_t isgn_parameter_count =
key.interpolator_count + key.has_point_size + 1 +
key.interpolator_count + 1 +
((input_clip_and_cull_distance_count + 3) / 4) +
uint32_t(input_cull_distance_count &&
(input_clip_distance_count & 3) != 0);
(input_clip_distance_count & 3) != 0) +
key.has_point_size;
// Reserve space for the header and the parameters.
shader_out[blob_offset_position_dwords] =
@@ -1910,7 +1970,7 @@ void PipelineCache::CreateDxbcGeometryShader(
name_ptr =
uint32_t((shader_out.size() - isgn_position_dwords) * sizeof(uint32_t));
uint32_t isgn_name_ptr_texcoord = name_ptr;
if (key.interpolator_count || key.has_point_size) {
if (key.interpolator_count) {
name_ptr += dxbc::AppendAlignedString(shader_out, "TEXCOORD");
}
uint32_t isgn_name_ptr_sv_position = name_ptr;
@@ -1923,12 +1983,16 @@ void PipelineCache::CreateDxbcGeometryShader(
if (input_cull_distance_count) {
name_ptr += dxbc::AppendAlignedString(shader_out, "SV_CullDistance");
}
uint32_t isgn_name_ptr_xepsize = name_ptr;
if (key.has_point_size) {
name_ptr += dxbc::AppendAlignedString(shader_out, "XEPSIZE");
}
// Header and parameters.
uint32_t input_register_interpolators = UINT32_MAX;
uint32_t input_register_point_size = UINT32_MAX;
uint32_t input_register_position;
uint32_t input_register_clip_and_cull_distances = UINT32_MAX;
uint32_t input_register_point_size = UINT32_MAX;
{
// Header.
auto& isgn_header = *reinterpret_cast<dxbc::Signature*>(
@@ -1960,27 +2024,7 @@ void PipelineCache::CreateDxbcGeometryShader(
}
}
// Point size.
// TODO(Triang3l): Put the size in X of float1, not in Z of float3, when
// linkage via shader modifications is done.
// TODO(Triang3l): Rename from TEXCOORD# to XEPSIZE when linkage via shader
// modifications is done.
if (key.has_point_size) {
input_register_point_size = input_register_index;
assert_true(isgn_parameter_index < isgn_parameter_count);
dxbc::SignatureParameter& isgn_point_size =
isgn_parameters[isgn_parameter_index++];
isgn_point_size.semantic_name_ptr = isgn_name_ptr_texcoord;
isgn_point_size.semantic_index = key.interpolator_count;
isgn_point_size.component_type =
dxbc::SignatureRegisterComponentType::kFloat32;
isgn_point_size.register_index = input_register_index++;
isgn_point_size.mask = 0b0111;
isgn_point_size.always_reads_mask =
key.type == PipelineGeometryShader::kPointList ? 0b0100 : 0;
}
// Position.
// Position (SV_Position).
input_register_position = input_register_index;
assert_true(isgn_parameter_index < isgn_parameter_count);
dxbc::SignatureParameter& isgn_sv_position =
@@ -1993,7 +2037,7 @@ void PipelineCache::CreateDxbcGeometryShader(
isgn_sv_position.mask = 0b1111;
isgn_sv_position.always_reads_mask = 0b1111;
// Clip and cull distances.
// Clip and cull distances (SV_ClipDistance#, SV_CullDistance#).
if (input_clip_and_cull_distance_count) {
input_register_clip_and_cull_distances = input_register_index;
uint32_t isgn_cull_distance_semantic_index = 0;
@@ -2041,6 +2085,21 @@ void PipelineCache::CreateDxbcGeometryShader(
}
}
// Point size (XEPSIZE).
if (key.has_point_size) {
input_register_point_size = input_register_index;
assert_true(isgn_parameter_index < isgn_parameter_count);
dxbc::SignatureParameter& isgn_point_size =
isgn_parameters[isgn_parameter_index++];
isgn_point_size.semantic_name_ptr = isgn_name_ptr_xepsize;
isgn_point_size.component_type =
dxbc::SignatureRegisterComponentType::kFloat32;
isgn_point_size.register_index = input_register_index++;
isgn_point_size.mask = 0b0001;
isgn_point_size.always_reads_mask =
key.type == PipelineGeometryShader::kPointList ? 0b0001 : 0;
}
assert_true(isgn_parameter_index == isgn_parameter_count);
}
@@ -2059,8 +2118,6 @@ void PipelineCache::CreateDxbcGeometryShader(
// ***************************************************************************
// Interpolators, point coordinates, position, clip distances.
// TODO(Triang3l): Reorder as needed when the respective changes are done in
// the shader translator.
uint32_t osgn_parameter_count = key.interpolator_count +
key.has_point_coordinates + 1 +
((input_clip_distance_count + 3) / 4);
@@ -2078,9 +2135,13 @@ void PipelineCache::CreateDxbcGeometryShader(
name_ptr =
uint32_t((shader_out.size() - osgn_position_dwords) * sizeof(uint32_t));
uint32_t osgn_name_ptr_texcoord = name_ptr;
if (key.interpolator_count || key.has_point_coordinates) {
if (key.interpolator_count) {
name_ptr += dxbc::AppendAlignedString(shader_out, "TEXCOORD");
}
uint32_t osgn_name_ptr_xespritetexcoord = name_ptr;
if (key.has_point_coordinates) {
name_ptr += dxbc::AppendAlignedString(shader_out, "XESPRITETEXCOORD");
}
uint32_t osgn_name_ptr_sv_position = name_ptr;
name_ptr += dxbc::AppendAlignedString(shader_out, "SV_Position");
uint32_t osgn_name_ptr_sv_clip_distance = name_ptr;
@@ -2123,26 +2184,21 @@ void PipelineCache::CreateDxbcGeometryShader(
}
}
// Point coordinates.
// TODO(Triang3l): Put the coordinates in XY of float2 when linkage via
// shader modifications is done.
// TODO(Triang3l): Rename from TEXCOORD# to XESPRITETEXCOORD when linkage
// via shader modifications is done.
// Point coordinates (XESPRITETEXCOORD).
if (key.has_point_coordinates) {
output_register_point_coordinates = output_register_index;
assert_true(osgn_parameter_index < osgn_parameter_count);
dxbc::SignatureParameterForGS& osgn_point_coordinates =
osgn_parameters[osgn_parameter_index++];
osgn_point_coordinates.semantic_name_ptr = osgn_name_ptr_texcoord;
osgn_point_coordinates.semantic_index = key.interpolator_count;
osgn_point_coordinates.semantic_name_ptr = osgn_name_ptr_xespritetexcoord;
osgn_point_coordinates.component_type =
dxbc::SignatureRegisterComponentType::kFloat32;
osgn_point_coordinates.register_index = output_register_index++;
osgn_point_coordinates.mask = 0b0111;
osgn_point_coordinates.mask = 0b0011;
osgn_point_coordinates.never_writes_mask = 0b1100;
}
// Position.
// Position (SV_Position).
output_register_position = output_register_index;
assert_true(osgn_parameter_index < osgn_parameter_count);
dxbc::SignatureParameterForGS& osgn_sv_position =
@@ -2154,7 +2210,7 @@ void PipelineCache::CreateDxbcGeometryShader(
osgn_sv_position.register_index = output_register_index++;
osgn_sv_position.mask = 0b1111;
// Clip distances.
// Clip distances (SV_ClipDistance#).
if (input_clip_distance_count) {
output_register_clip_distances = output_register_index;
for (uint32_t i = 0; i < input_clip_distance_count; i += 4) {
@@ -2256,11 +2312,6 @@ void PipelineCache::CreateDxbcGeometryShader(
a.OpDclInput(dxbc::Dest::V2D(input_primitive_vertex_count,
input_register_interpolators + i));
}
if (key.has_point_size && key.type == PipelineGeometryShader::kPointList) {
assert_true(input_register_point_size != UINT32_MAX);
a.OpDclInput(dxbc::Dest::V2D(input_primitive_vertex_count,
input_register_point_size, 0b0100));
}
a.OpDclInputSIV(
dxbc::Dest::V2D(input_primitive_vertex_count, input_register_position),
dxbc::Name::kPosition);
@@ -2292,6 +2343,11 @@ void PipelineCache::CreateDxbcGeometryShader(
cull_distance_mask));
}
}
if (key.has_point_size && key.type == PipelineGeometryShader::kPointList) {
assert_true(input_register_point_size != UINT32_MAX);
a.OpDclInput(dxbc::Dest::V2D(input_primitive_vertex_count,
input_register_point_size, 0b0001));
}
// At least 1 temporary register needed to discard primitives with NaN
// position.
@@ -2394,10 +2450,10 @@ void PipelineCache::CreateDxbcGeometryShader(
// constant size. The per-vertex diameter is already clamped in the
// vertex shader (combined with making it non-negative).
a.OpGE(dxbc::Dest::R(0, 0b0001),
dxbc::Src::V2D(0, input_register_point_size, dxbc::Src::kZZZZ),
dxbc::Src::V2D(0, input_register_point_size, dxbc::Src::kXXXX),
dxbc::Src::LF(0.0f));
a.OpMovC(dxbc::Dest::R(0, 0b0011), dxbc::Src::R(0, dxbc::Src::kXXXX),
dxbc::Src::V2D(0, input_register_point_size, dxbc::Src::kZZZZ),
dxbc::Src::V2D(0, input_register_point_size, dxbc::Src::kXXXX),
point_size_src);
point_size_src = dxbc::Src::R(0, 0b0100);
}

View File

@@ -78,9 +78,10 @@ class PipelineCache {
// have microcode analyzed.
DxbcShaderTranslator::Modification GetCurrentVertexShaderModification(
const Shader& shader,
Shader::HostVertexShaderType host_vertex_shader_type) const;
Shader::HostVertexShaderType host_vertex_shader_type,
uint32_t interpolator_mask) const;
DxbcShaderTranslator::Modification GetCurrentPixelShaderModification(
const Shader& shader,
const Shader& shader, uint32_t interpolator_mask, uint32_t param_gen_pos,
reg::RB_DEPTHCONTROL normalized_depth_control) const;
// If draw_util::IsRasterizationPotentiallyDone is false, the pixel shader
@@ -290,8 +291,11 @@ class PipelineCache {
const uint32_t* bound_depth_and_color_render_target_formats,
PipelineRuntimeDescription& runtime_description_out);
static bool GetGeometryShaderKey(PipelineGeometryShader geometry_shader_type,
GeometryShaderKey& key_out);
static bool GetGeometryShaderKey(
PipelineGeometryShader geometry_shader_type,
DxbcShaderTranslator::Modification vertex_shader_modification,
DxbcShaderTranslator::Modification pixel_shader_modification,
GeometryShaderKey& key_out);
static void CreateDxbcGeometryShader(GeometryShaderKey key,
std::vector<uint32_t>& shader_out);
const std::vector<uint32_t>& GetGeometryShader(GeometryShaderKey key);