Merge branch 'master' into vulkan

This commit is contained in:
Triang3l
2021-06-08 12:15:34 +03:00
607 changed files with 452347 additions and 127070 deletions

View File

@@ -18,6 +18,7 @@
#include "xenia/base/math.h"
#include "xenia/base/profiling.h"
#include "xenia/base/xxhash.h"
#include "xenia/gpu/draw_util.h"
#include "xenia/gpu/gpu_flags.h"
#include "xenia/gpu/register_file.h"
#include "xenia/gpu/registers.h"
@@ -82,7 +83,6 @@ void VulkanPipelineCache::ClearCache() {
}
VulkanShader* VulkanPipelineCache::LoadShader(xenos::ShaderType shader_type,
uint32_t guest_address,
const uint32_t* host_address,
uint32_t dword_count) {
// Hash the input memory and lookup the shader.
@@ -93,7 +93,6 @@ VulkanShader* VulkanPipelineCache::LoadShader(xenos::ShaderType shader_type,
// Shader has been previously loaded.
return it->second;
}
// Always create the shader and stash it away.
// We need to track it even if it fails translation so we know not to try
// again.
@@ -101,53 +100,34 @@ VulkanShader* VulkanPipelineCache::LoadShader(xenos::ShaderType shader_type,
shader_type, data_hash, host_address, dword_count,
command_processor_.GetVulkanContext().GetVulkanProvider());
shaders_.emplace(data_hash, shader);
if (!cvars::dump_shaders.empty()) {
shader->DumpUcodeBinary(cvars::dump_shaders);
}
return shader;
}
bool VulkanPipelineCache::GetCurrentShaderModifications(
SpirvShaderTranslator::Modification& vertex_shader_modification_out,
SpirvShaderTranslator::Modification& pixel_shader_modification_out) const {
// TODO(Triang3l): Tessellation, depth output.
vertex_shader_modification_out = SpirvShaderTranslator::Modification(
shader_translator_->GetDefaultModification(xenos::ShaderType::kVertex));
pixel_shader_modification_out = SpirvShaderTranslator::Modification(
shader_translator_->GetDefaultModification(xenos::ShaderType::kPixel));
return true;
SpirvShaderTranslator::Modification
VulkanPipelineCache::GetCurrentVertexShaderModification(
const Shader& shader,
Shader::HostVertexShaderType host_vertex_shader_type) 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 SpirvShaderTranslator::Modification(
shader_translator_->GetDefaultVertexShaderModification(
shader.GetDynamicAddressableRegisterCount(sq_program_cntl.vs_num_reg),
host_vertex_shader_type));
}
bool VulkanPipelineCache::EnsureShadersTranslated(
VulkanShader::VulkanTranslation* vertex_shader,
VulkanShader::VulkanTranslation* pixel_shader) {
const RegisterFile& regs = register_file_;
SpirvShaderTranslator::Modification
VulkanPipelineCache::GetCurrentPixelShaderModification(
const Shader& shader) 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>();
// Edge flags are not supported yet (because polygon primitives are not).
assert_true(sq_program_cntl.vs_export_mode !=
xenos::VertexShaderExportMode::kPosition2VectorsEdge &&
sq_program_cntl.vs_export_mode !=
xenos::VertexShaderExportMode::kPosition2VectorsEdgeKill);
assert_false(sq_program_cntl.gen_index_vtx);
if (!vertex_shader->is_translated()) {
if (!TranslateShader(*shader_translator_, *vertex_shader,
sq_program_cntl)) {
XELOGE("Failed to translate the vertex shader!");
return false;
}
}
if (pixel_shader != nullptr && !pixel_shader->is_translated()) {
if (!TranslateShader(*shader_translator_, *pixel_shader, sq_program_cntl)) {
XELOGE("Failed to translate the pixel shader!");
return false;
}
}
return true;
return SpirvShaderTranslator::Modification(
shader_translator_->GetDefaultPixelShaderModification(
shader.GetDynamicAddressableRegisterCount(
sq_program_cntl.ps_num_reg)));
}
bool VulkanPipelineCache::ConfigurePipeline(
@@ -160,6 +140,38 @@ bool VulkanPipelineCache::ConfigurePipeline(
SCOPE_profile_cpu_f("gpu");
#endif // XE_UI_VULKAN_FINE_GRAINED_DRAW_SCOPES
// Ensure shaders are translated - needed now for GetCurrentStateDescription.
// Edge flags are not supported yet (because polygon primitives are not).
assert_true(register_file_.Get<reg::SQ_PROGRAM_CNTL>().vs_export_mode !=
xenos::VertexShaderExportMode::kPosition2VectorsEdge &&
register_file_.Get<reg::SQ_PROGRAM_CNTL>().vs_export_mode !=
xenos::VertexShaderExportMode::kPosition2VectorsEdgeKill);
assert_false(register_file_.Get<reg::SQ_PROGRAM_CNTL>().gen_index_vtx);
if (!vertex_shader->is_translated()) {
vertex_shader->shader().AnalyzeUcode(ucode_disasm_buffer_);
if (!TranslateAnalyzedShader(*shader_translator_, *vertex_shader)) {
XELOGE("Failed to translate the vertex shader!");
return false;
}
}
if (!vertex_shader->is_valid()) {
// Translation attempted previously, but not valid.
return false;
}
if (pixel_shader != nullptr) {
if (!pixel_shader->is_translated()) {
pixel_shader->shader().AnalyzeUcode(ucode_disasm_buffer_);
if (!TranslateAnalyzedShader(*shader_translator_, *pixel_shader)) {
XELOGE("Failed to translate the pixel shader!");
return false;
}
}
if (!pixel_shader->is_valid()) {
// Translation attempted previously, but not valid.
return false;
}
}
PipelineDescription description;
if (!GetCurrentStateDescription(vertex_shader, pixel_shader, render_pass_key,
description)) {
@@ -179,9 +191,6 @@ bool VulkanPipelineCache::ConfigurePipeline(
}
// Create the pipeline if not the latest and not already existing.
if (!EnsureShadersTranslated(vertex_shader, pixel_shader)) {
return false;
}
const PipelineLayoutProvider* pipeline_layout =
command_processor_.GetPipelineLayout(0, 0);
if (!pipeline_layout) {
@@ -207,12 +216,12 @@ bool VulkanPipelineCache::ConfigurePipeline(
return true;
}
bool VulkanPipelineCache::TranslateShader(
bool VulkanPipelineCache::TranslateAnalyzedShader(
SpirvShaderTranslator& translator,
VulkanShader::VulkanTranslation& translation, reg::SQ_PROGRAM_CNTL cntl) {
VulkanShader::VulkanTranslation& translation) {
// Perform translation.
// If this fails the shader will be marked as invalid and ignored later.
if (!translator.Translate(translation, cntl)) {
if (!translator.TranslateAnalyzedShader(translation)) {
XELOGE("Shader {:016X} translation failed; marking as ignored",
translation.shader().ucode_data_hash());
return false;
@@ -283,7 +292,7 @@ bool VulkanPipelineCache::GetCurrentStateDescription(
primitive_restart_allowed && pa_su_sc_mode_cntl.multi_prim_ib_ena;
// TODO(Triang3l): Tessellation.
bool primitive_polygonal = xenos::IsPrimitivePolygonal(false, primitive_type);
bool primitive_polygonal = draw_util::IsPrimitivePolygonal(regs);
if (primitive_polygonal) {
// Vulkan only allows the polygon mode to be set for both faces - pick the
// most special one (more likely to represent the developer's deliberate