[GPU] Non-ROV f24 trunc/round, host shader modifications, cache dir
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user