[GPU] Non-ROV f24 trunc/round, host shader modifications, cache dir

This commit is contained in:
Triang3l
2020-12-07 22:23:54 +03:00
parent a86609e93a
commit 9a4643d0f2
71 changed files with 3656 additions and 1633 deletions

View File

@@ -362,35 +362,38 @@ VkPipeline PipelineCache::GetPipeline(const RenderState* render_state,
return pipeline;
}
bool PipelineCache::TranslateShader(VulkanShader* shader,
reg::SQ_PROGRAM_CNTL cntl) {
bool PipelineCache::TranslateShader(
VulkanShader::VulkanTranslation& translation, reg::SQ_PROGRAM_CNTL cntl) {
// Perform translation.
// If this fails the shader will be marked as invalid and ignored later.
if (!shader_translator_->Translate(shader, cntl)) {
if (!shader_translator_->Translate(translation, cntl)) {
XELOGE("Shader translation failed; marking shader as ignored");
return false;
}
// Prepare the shader for use (creates our VkShaderModule).
// It could still fail at this point.
if (!shader->Prepare()) {
if (!translation.Prepare()) {
XELOGE("Shader preparation failed; marking shader as ignored");
return false;
}
if (shader->is_valid()) {
if (translation.is_valid()) {
XELOGGPU("Generated {} shader ({}b) - hash {:016X}:\n{}\n",
shader->type() == xenos::ShaderType::kVertex ? "vertex" : "pixel",
shader->ucode_dword_count() * 4, shader->ucode_data_hash(),
shader->ucode_disassembly());
translation.shader().type() == xenos::ShaderType::kVertex
? "vertex"
: "pixel",
translation.shader().ucode_dword_count() * 4,
translation.shader().ucode_data_hash(),
translation.shader().ucode_disassembly());
}
// Dump shader files if desired.
if (!cvars::dump_shaders.empty()) {
shader->Dump(cvars::dump_shaders, "vk");
translation.Dump(cvars::dump_shaders, "vk");
}
return shader->is_valid();
return translation.is_valid();
}
static void DumpShaderStatisticsAMD(const VkShaderStatisticsInfoAMD& stats) {
@@ -1063,16 +1066,28 @@ PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages(
return UpdateStatus::kCompatible;
}
if (!vertex_shader->is_translated() &&
!TranslateShader(vertex_shader, regs.sq_program_cntl)) {
VulkanShader::VulkanTranslation* vertex_shader_translation =
static_cast<VulkanShader::VulkanTranslation*>(
vertex_shader->GetOrCreateTranslation(
shader_translator_->GetDefaultModification(
xenos::ShaderType::kVertex)));
if (!vertex_shader_translation->is_translated() &&
!TranslateShader(*vertex_shader_translation, regs.sq_program_cntl)) {
XELOGE("Failed to translate the vertex shader!");
return UpdateStatus::kError;
}
if (pixel_shader && !pixel_shader->is_translated() &&
!TranslateShader(pixel_shader, regs.sq_program_cntl)) {
XELOGE("Failed to translate the pixel shader!");
return UpdateStatus::kError;
VulkanShader::VulkanTranslation* pixel_shader_translation = nullptr;
if (pixel_shader) {
pixel_shader_translation = static_cast<VulkanShader::VulkanTranslation*>(
pixel_shader->GetOrCreateTranslation(
shader_translator_->GetDefaultModification(
xenos::ShaderType::kPixel)));
if (!pixel_shader_translation->is_translated() &&
!TranslateShader(*pixel_shader_translation, regs.sq_program_cntl)) {
XELOGE("Failed to translate the pixel shader!");
return UpdateStatus::kError;
}
}
update_shader_stages_stage_count_ = 0;
@@ -1084,7 +1099,7 @@ PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages(
vertex_pipeline_stage.pNext = nullptr;
vertex_pipeline_stage.flags = 0;
vertex_pipeline_stage.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertex_pipeline_stage.module = vertex_shader->shader_module();
vertex_pipeline_stage.module = vertex_shader_translation->shader_module();
vertex_pipeline_stage.pName = "main";
vertex_pipeline_stage.pSpecializationInfo = nullptr;
@@ -1116,8 +1131,9 @@ PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages(
pixel_pipeline_stage.pNext = nullptr;
pixel_pipeline_stage.flags = 0;
pixel_pipeline_stage.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
pixel_pipeline_stage.module =
pixel_shader ? pixel_shader->shader_module() : dummy_pixel_shader_;
pixel_pipeline_stage.module = pixel_shader_translation
? pixel_shader_translation->shader_module()
: dummy_pixel_shader_;
pixel_pipeline_stage.pName = "main";
pixel_pipeline_stage.pSpecializationInfo = nullptr;

View File

@@ -79,7 +79,8 @@ class PipelineCache {
// state.
VkPipeline GetPipeline(const RenderState* render_state, uint64_t hash_key);
bool TranslateShader(VulkanShader* shader, reg::SQ_PROGRAM_CNTL cntl);
bool TranslateShader(VulkanShader::VulkanTranslation& translation,
reg::SQ_PROGRAM_CNTL cntl);
void DumpShaderDisasmAMD(VkPipeline pipeline);
void DumpShaderDisasmNV(const VkGraphicsPipelineCreateInfo& info);

View File

@@ -27,38 +27,56 @@ VulkanShader::VulkanShader(ui::vulkan::VulkanDevice* device,
const uint32_t* dword_ptr, uint32_t dword_count)
: Shader(shader_type, data_hash, dword_ptr, dword_count), device_(device) {}
VulkanShader::~VulkanShader() {
VulkanShader::VulkanTranslation::~VulkanTranslation() {
if (shader_module_) {
vkDestroyShaderModule(*device_, shader_module_, nullptr);
const VulkanShader& vulkan_shader = static_cast<VulkanShader&>(shader());
vkDestroyShaderModule(*vulkan_shader.device_, shader_module_, nullptr);
shader_module_ = nullptr;
}
}
bool VulkanShader::Prepare() {
bool VulkanShader::VulkanTranslation::Prepare() {
assert_null(shader_module_);
assert_true(is_valid());
const VulkanShader& vulkan_shader = static_cast<VulkanShader&>(shader());
ui::vulkan::VulkanDevice* device = vulkan_shader.device_;
// Create the shader module.
VkShaderModuleCreateInfo shader_info;
shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shader_info.pNext = nullptr;
shader_info.flags = 0;
shader_info.codeSize = translated_binary_.size();
shader_info.codeSize = translated_binary().size();
shader_info.pCode =
reinterpret_cast<const uint32_t*>(translated_binary_.data());
reinterpret_cast<const uint32_t*>(translated_binary().data());
auto status =
vkCreateShaderModule(*device_, &shader_info, nullptr, &shader_module_);
vkCreateShaderModule(*device, &shader_info, nullptr, &shader_module_);
CheckResult(status, "vkCreateShaderModule");
char typeChar = shader_type_ == xenos::ShaderType::kPixel
? 'p'
: shader_type_ == xenos::ShaderType::kVertex ? 'v' : 'u';
device_->DbgSetObjectName(
uint64_t(shader_module_), VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT,
fmt::format("S({}): {:016X}", typeChar, ucode_data_hash()));
char type_char;
switch (vulkan_shader.type()) {
case xenos::ShaderType::kVertex:
type_char = 'v';
break;
case xenos::ShaderType::kPixel:
type_char = 'p';
break;
default:
type_char = 'u';
}
device->DbgSetObjectName(uint64_t(shader_module_),
VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT,
fmt::format("S({}): {:016X}", type_char,
vulkan_shader.ucode_data_hash()));
return status == VK_SUCCESS;
}
Shader::Translation* VulkanShader::CreateTranslationInstance(
uint32_t modification) {
return new VulkanTranslation(*this, modification);
}
} // namespace vulkan
} // namespace gpu
} // namespace xe

View File

@@ -21,19 +21,30 @@ namespace vulkan {
class VulkanShader : public Shader {
public:
class VulkanTranslation : public Translation {
public:
VulkanTranslation(VulkanShader& shader, uint32_t modification)
: Translation(shader, modification) {}
~VulkanTranslation() override;
bool Prepare();
// Available only if the translation is_valid and has been prepared.
VkShaderModule shader_module() const { return shader_module_; }
private:
VkShaderModule shader_module_ = nullptr;
};
VulkanShader(ui::vulkan::VulkanDevice* device, xenos::ShaderType shader_type,
uint64_t data_hash, const uint32_t* dword_ptr,
uint32_t dword_count);
~VulkanShader() override;
// Available only if the shader is_valid and has been prepared.
VkShaderModule shader_module() const { return shader_module_; }
bool Prepare();
protected:
Translation* CreateTranslationInstance(uint32_t modification) override;
private:
ui::vulkan::VulkanDevice* device_ = nullptr;
VkShaderModule shader_module_ = nullptr;
};
} // namespace vulkan