[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();
unique_texture_bindings_ = 0;
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) {
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);
}
GatherBindingInformation(cf_a);
GatherBindingInformation(cf_b);
GatherInstructionInformation(cf_a);
GatherInstructionInformation(cf_b);
}
shader->vertex_bindings_ = std::move(vertex_bindings_);
@ -117,7 +118,8 @@ bool ShaderTranslator::TranslateInternal(Shader* shader) {
ucode_dwords_ = shader->ucode_dwords();
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.
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) {
@ -133,8 +135,8 @@ bool ShaderTranslator::TranslateInternal(Shader* shader) {
std::min(max_cf_dword_index, cf_b.exec.address() * 3);
}
GatherBindingInformation(cf_a);
GatherBindingInformation(cf_b);
GatherInstructionInformation(cf_a);
GatherInstructionInformation(cf_b);
}
StartTranslation();
@ -225,7 +227,7 @@ void ShaderTranslator::EmitUnimplementedTranslationError() {
errors_.push_back(std::move(error));
}
void ShaderTranslator::GatherBindingInformation(
void ShaderTranslator::GatherInstructionInformation(
const ControlFlowInstruction& cf) {
switch (cf.opcode()) {
case ControlFlowOpcode::kExec:
@ -247,24 +249,52 @@ void ShaderTranslator::GatherBindingInformation(
static_cast<FetchOpcode>(ucode_dwords_[instr_offset * 3] & 0x1F);
if (fetch_opcode == FetchOpcode::kVertexFetch) {
assert_true(is_vertex_shader());
GatherVertexBindingInformation(
GatherVertexFetchInformation(
*reinterpret_cast<const VertexFetchInstruction*>(
ucode_dwords_ + instr_offset * 3));
} else {
GatherTextureBindingInformation(
GatherTextureFetchInformation(
*reinterpret_cast<const TextureFetchInstruction*>(
ucode_dwords_ + instr_offset * 3));
}
} else if (is_pixel_shader()) {
// Gather up color targets written to.
} else {
// Gather up color targets written to, and check if using dynamic
// register indices.
auto& op = *reinterpret_cast<const AluInstruction*>(ucode_dwords_ +
instr_offset * 3);
if (op.is_export()) {
if (op.has_vector_op() && op.vector_dest() <= 3) {
writes_color_targets_[op.vector_dest()] = true;
if (op.has_vector_op()) {
const auto& opcode_info =
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) {
writes_color_targets_[op.scalar_dest()] = true;
if (op.is_export()) {
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) {
ParsedVertexFetchInstruction fetch_instr;
ParseVertexFetchInstruction(op, &fetch_instr);
@ -285,6 +315,11 @@ void ShaderTranslator::GatherVertexBindingInformation(
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.
// If no binding for this fetch slot is found create it.
using VertexBinding = Shader::VertexBinding;
@ -317,8 +352,13 @@ void ShaderTranslator::GatherVertexBindingInformation(
GetVertexFormatSizeInWords(attrib->fetch_instr.attributes.data_format);
}
void ShaderTranslator::GatherTextureBindingInformation(
void ShaderTranslator::GatherTextureFetchInformation(
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()) {
case FetchOpcode::kSetTextureLod:
case FetchOpcode::kSetTextureGradientsHorz:

View File

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