[GPU] Detect dynamic temp indexing before translating shaders

This commit is contained in:
Triang3l 2018-08-31 20:06:53 +03:00
parent 8c314072c8
commit dad10c30e9
2 changed files with 61 additions and 21 deletions

View File

@ -58,6 +58,7 @@ void ShaderTranslator::Reset() {
texture_bindings_.clear(); texture_bindings_.clear();
unique_texture_bindings_ = 0; unique_texture_bindings_ = 0;
std::memset(&constant_register_map_, 0, sizeof(constant_register_map_)); std::memset(&constant_register_map_, 0, sizeof(constant_register_map_));
uses_register_relative_addressing_ = false;
for (size_t i = 0; i < xe::countof(writes_color_targets_); ++i) { for (size_t i = 0; i < xe::countof(writes_color_targets_); ++i) {
writes_color_targets_[i] = false; writes_color_targets_[i] = false;
} }
@ -85,8 +86,8 @@ bool ShaderTranslator::GatherAllBindingInformation(Shader* shader) {
std::min(max_cf_dword_index, cf_b.exec.address() * 3); std::min(max_cf_dword_index, cf_b.exec.address() * 3);
} }
GatherBindingInformation(cf_a); GatherInstructionInformation(cf_a);
GatherBindingInformation(cf_b); GatherInstructionInformation(cf_b);
} }
shader->vertex_bindings_ = std::move(vertex_bindings_); shader->vertex_bindings_ = std::move(vertex_bindings_);
@ -117,7 +118,8 @@ bool ShaderTranslator::TranslateInternal(Shader* shader) {
ucode_dwords_ = shader->ucode_dwords(); ucode_dwords_ = shader->ucode_dwords();
ucode_dword_count_ = shader->ucode_dword_count(); ucode_dword_count_ = shader->ucode_dword_count();
// Run through and gather all binding information. // Run through and gather all binding information and to check whether
// registers are dynamically addressed.
// Translators may need this before they start codegen. // Translators may need this before they start codegen.
uint32_t max_cf_dword_index = static_cast<uint32_t>(ucode_dword_count_); uint32_t max_cf_dword_index = static_cast<uint32_t>(ucode_dword_count_);
for (uint32_t i = 0; i < max_cf_dword_index; i += 3) { for (uint32_t i = 0; i < max_cf_dword_index; i += 3) {
@ -133,8 +135,8 @@ bool ShaderTranslator::TranslateInternal(Shader* shader) {
std::min(max_cf_dword_index, cf_b.exec.address() * 3); std::min(max_cf_dword_index, cf_b.exec.address() * 3);
} }
GatherBindingInformation(cf_a); GatherInstructionInformation(cf_a);
GatherBindingInformation(cf_b); GatherInstructionInformation(cf_b);
} }
StartTranslation(); StartTranslation();
@ -225,7 +227,7 @@ void ShaderTranslator::EmitUnimplementedTranslationError() {
errors_.push_back(std::move(error)); errors_.push_back(std::move(error));
} }
void ShaderTranslator::GatherBindingInformation( void ShaderTranslator::GatherInstructionInformation(
const ControlFlowInstruction& cf) { const ControlFlowInstruction& cf) {
switch (cf.opcode()) { switch (cf.opcode()) {
case ControlFlowOpcode::kExec: case ControlFlowOpcode::kExec:
@ -247,24 +249,52 @@ void ShaderTranslator::GatherBindingInformation(
static_cast<FetchOpcode>(ucode_dwords_[instr_offset * 3] & 0x1F); static_cast<FetchOpcode>(ucode_dwords_[instr_offset * 3] & 0x1F);
if (fetch_opcode == FetchOpcode::kVertexFetch) { if (fetch_opcode == FetchOpcode::kVertexFetch) {
assert_true(is_vertex_shader()); assert_true(is_vertex_shader());
GatherVertexBindingInformation( GatherVertexFetchInformation(
*reinterpret_cast<const VertexFetchInstruction*>( *reinterpret_cast<const VertexFetchInstruction*>(
ucode_dwords_ + instr_offset * 3)); ucode_dwords_ + instr_offset * 3));
} else { } else {
GatherTextureBindingInformation( GatherTextureFetchInformation(
*reinterpret_cast<const TextureFetchInstruction*>( *reinterpret_cast<const TextureFetchInstruction*>(
ucode_dwords_ + instr_offset * 3)); ucode_dwords_ + instr_offset * 3));
} }
} else if (is_pixel_shader()) { } else {
// Gather up color targets written to. // Gather up color targets written to, and check if using dynamic
// register indices.
auto& op = *reinterpret_cast<const AluInstruction*>(ucode_dwords_ + auto& op = *reinterpret_cast<const AluInstruction*>(ucode_dwords_ +
instr_offset * 3); instr_offset * 3);
if (op.is_export()) { if (op.has_vector_op()) {
if (op.has_vector_op() && op.vector_dest() <= 3) { const auto& opcode_info =
writes_color_targets_[op.vector_dest()] = true; alu_vector_opcode_infos_[static_cast<int>(op.vector_opcode())];
for (size_t i = 0; i < opcode_info.argument_count; ++i) {
if (op.src_is_temp(i) && (op.src_reg(i) & 0x40)) {
uses_register_relative_addressing_ = true;
}
} }
if (op.has_scalar_op() && op.scalar_dest() <= 3) { if (op.is_export()) {
writes_color_targets_[op.scalar_dest()] = true; if (is_pixel_shader() && op.vector_dest() <= 3) {
writes_color_targets_[op.vector_dest()] = true;
}
} else {
if (op.is_vector_dest_relative()) {
uses_register_relative_addressing_ = true;
}
}
}
if (op.has_scalar_op()) {
const auto& opcode_info =
alu_scalar_opcode_infos_[static_cast<int>(op.scalar_opcode())];
if (opcode_info.argument_count == 1 && op.src_is_temp(0) &&
(op.src_reg(0) & 0x40)) {
uses_register_relative_addressing_ = true;
}
if (op.is_export()) {
if (is_pixel_shader() && op.scalar_dest() <= 3) {
writes_color_targets_[op.scalar_dest()] = true;
}
} else {
if (op.is_scalar_dest_relative()) {
uses_register_relative_addressing_ = true;
}
} }
} }
} }
@ -275,7 +305,7 @@ void ShaderTranslator::GatherBindingInformation(
} }
} }
void ShaderTranslator::GatherVertexBindingInformation( void ShaderTranslator::GatherVertexFetchInformation(
const VertexFetchInstruction& op) { const VertexFetchInstruction& op) {
ParsedVertexFetchInstruction fetch_instr; ParsedVertexFetchInstruction fetch_instr;
ParseVertexFetchInstruction(op, &fetch_instr); ParseVertexFetchInstruction(op, &fetch_instr);
@ -285,6 +315,11 @@ void ShaderTranslator::GatherVertexBindingInformation(
return; return;
} }
// Check if using dynamic register indices.
if (op.is_dest_relative() || op.is_src_relative()) {
uses_register_relative_addressing_ = true;
}
// Try to allocate an attribute on an existing binding. // Try to allocate an attribute on an existing binding.
// If no binding for this fetch slot is found create it. // If no binding for this fetch slot is found create it.
using VertexBinding = Shader::VertexBinding; using VertexBinding = Shader::VertexBinding;
@ -317,8 +352,13 @@ void ShaderTranslator::GatherVertexBindingInformation(
GetVertexFormatSizeInWords(attrib->fetch_instr.attributes.data_format); GetVertexFormatSizeInWords(attrib->fetch_instr.attributes.data_format);
} }
void ShaderTranslator::GatherTextureBindingInformation( void ShaderTranslator::GatherTextureFetchInformation(
const TextureFetchInstruction& op) { const TextureFetchInstruction& op) {
// Check if using dynamic register indices.
if (op.is_dest_relative() || op.is_src_relative()) {
uses_register_relative_addressing_ = true;
}
switch (op.opcode()) { switch (op.opcode()) {
case FetchOpcode::kSetTextureLod: case FetchOpcode::kSetTextureLod:
case FetchOpcode::kSetTextureGradientsHorz: case FetchOpcode::kSetTextureGradientsHorz:

View File

@ -143,10 +143,9 @@ class ShaderTranslator {
void AppendUcodeDisasmFormat(const char* format, ...); void AppendUcodeDisasmFormat(const char* format, ...);
bool TranslateBlocks(); bool TranslateBlocks();
void GatherBindingInformation(const ucode::ControlFlowInstruction& cf); void GatherInstructionInformation(const ucode::ControlFlowInstruction& cf);
void GatherVertexBindingInformation(const ucode::VertexFetchInstruction& op); void GatherVertexFetchInformation(const ucode::VertexFetchInstruction& op);
void GatherTextureBindingInformation( void GatherTextureFetchInformation(const ucode::TextureFetchInstruction& op);
const ucode::TextureFetchInstruction& op);
void TranslateControlFlowInstruction(const ucode::ControlFlowInstruction& cf); void TranslateControlFlowInstruction(const ucode::ControlFlowInstruction& cf);
void TranslateControlFlowNop(const ucode::ControlFlowInstruction& cf); void TranslateControlFlowNop(const ucode::ControlFlowInstruction& cf);
void TranslateControlFlowExec(const ucode::ControlFlowExecInstruction& cf); void TranslateControlFlowExec(const ucode::ControlFlowExecInstruction& cf);
@ -216,6 +215,7 @@ class ShaderTranslator {
uint32_t unique_texture_bindings_ = 0; uint32_t unique_texture_bindings_ = 0;
Shader::ConstantRegisterMap constant_register_map_ = {0}; Shader::ConstantRegisterMap constant_register_map_ = {0};
bool uses_register_relative_addressing_ = false;
bool writes_color_targets_[4] = {false, false, false, false}; bool writes_color_targets_[4] = {false, false, false, false};
static const AluOpcodeInfo alu_vector_opcode_infos_[0x20]; static const AluOpcodeInfo alu_vector_opcode_infos_[0x20];