diff --git a/src/xenia/gpu/gl4/gl4_command_processor.cc b/src/xenia/gpu/gl4/gl4_command_processor.cc index 222d7e672..b1162a4b9 100644 --- a/src/xenia/gpu/gl4/gl4_command_processor.cc +++ b/src/xenia/gpu/gl4/gl4_command_processor.cc @@ -482,13 +482,20 @@ Shader* GL4CommandProcessor::LoadShader(ShaderType shader_type, shader_ptr = it->second; } else { // Not found in cache. - // No translation is performed here, as it depends on program_cntl. auto shader = std::make_unique(shader_type, hash, host_address, dword_count); shader_ptr = shader.get(); shader_cache_.insert({hash, shader_ptr}); all_shaders_.emplace_back(std::move(shader)); + // Perform translation. + // If this fails the shader will be marked as invalid and ignored later. + if (shader_type == ShaderType::kVertex) { + shader_ptr->PrepareVertexShader(&shader_translator_); + } else { + shader_ptr->PreparePixelShader(&shader_translator_); + } + XELOGGPU("Set %s shader at %0.8X (%db):\n%s", shader_type == ShaderType::kVertex ? "vertex" : "pixel", guest_address, dword_count * 4, @@ -626,24 +633,19 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::UpdateShaders( xe_gpu_program_cntl_t program_cntl; program_cntl.dword_0 = regs.sq_program_cntl; - if (!regs.vertex_shader->has_prepared()) { - if (!regs.vertex_shader->PrepareVertexShader(&shader_translator_, - program_cntl)) { - XELOGE("Unable to prepare vertex shader"); - return UpdateStatus::kError; - } - } else if (!regs.vertex_shader->is_valid()) { + + // Normal vertex shaders only, for now. + // TODO(benvanik): transform feedback/memexport. + // 0 = normal + // 2 = point size + assert_true(program_cntl.vs_export_mode == 0 || + program_cntl.vs_export_mode == 2); + + if (!regs.vertex_shader->is_valid()) { XELOGE("Vertex shader invalid"); return UpdateStatus::kError; } - - if (!regs.pixel_shader->has_prepared()) { - if (!regs.pixel_shader->PreparePixelShader(&shader_translator_, - program_cntl)) { - XELOGE("Unable to prepare pixel shader"); - return UpdateStatus::kError; - } - } else if (!regs.pixel_shader->is_valid()) { + if (!regs.pixel_shader->is_valid()) { XELOGE("Pixel shader invalid"); return UpdateStatus::kError; } diff --git a/src/xenia/gpu/gl4/gl4_shader.cc b/src/xenia/gpu/gl4/gl4_shader.cc index 023c99b87..256964575 100644 --- a/src/xenia/gpu/gl4/gl4_shader.cc +++ b/src/xenia/gpu/gl4/gl4_shader.cc @@ -198,13 +198,11 @@ bool GL4Shader::PrepareVertexArrayObject() { return true; } -bool GL4Shader::PrepareVertexShader( - GL4ShaderTranslator* shader_translator, - const xenos::xe_gpu_program_cntl_t& program_cntl) { - if (has_prepared_) { +bool GL4Shader::PrepareVertexShader(GL4ShaderTranslator* shader_translator) { + if (is_valid_) { return is_valid_; } - has_prepared_ = true; + is_valid_ = false; // Build static vertex array descriptor. if (!PrepareVertexArrayObject()) { @@ -253,7 +251,7 @@ bool GL4Shader::PrepareVertexShader( GetFooter(); std::string translated_source = - shader_translator->TranslateVertexShader(this, program_cntl); + shader_translator->TranslateVertexShader(this); if (translated_source.empty()) { XELOGE("Vertex shader failed translation"); return false; @@ -268,13 +266,11 @@ bool GL4Shader::PrepareVertexShader( return true; } -bool GL4Shader::PreparePixelShader( - GL4ShaderTranslator* shader_translator, - const xenos::xe_gpu_program_cntl_t& program_cntl) { - if (has_prepared_) { +bool GL4Shader::PreparePixelShader(GL4ShaderTranslator* shader_translator) { + if (is_valid_) { return is_valid_; } - has_prepared_ = true; + is_valid_ = false; std::string source = GetHeader() + @@ -306,8 +302,7 @@ bool GL4Shader::PreparePixelShader( "}\n" + GetFooter(); - std::string translated_source = - shader_translator->TranslatePixelShader(this, program_cntl); + std::string translated_source = shader_translator->TranslatePixelShader(this); if (translated_source.empty()) { XELOGE("Pixel shader failed translation"); return false; diff --git a/src/xenia/gpu/gl4/gl4_shader.h b/src/xenia/gpu/gl4/gl4_shader.h index 9e9077395..7e173dcf6 100644 --- a/src/xenia/gpu/gl4/gl4_shader.h +++ b/src/xenia/gpu/gl4/gl4_shader.h @@ -30,10 +30,8 @@ class GL4Shader : public Shader { GLuint program() const { return program_; } GLuint vao() const { return vao_; } - bool PrepareVertexShader(GL4ShaderTranslator* shader_translator, - const xenos::xe_gpu_program_cntl_t& program_cntl); - bool PreparePixelShader(GL4ShaderTranslator* shader_translator, - const xenos::xe_gpu_program_cntl_t& program_cntl); + bool PrepareVertexShader(GL4ShaderTranslator* shader_translator); + bool PreparePixelShader(GL4ShaderTranslator* shader_translator); protected: std::string GetHeader(); diff --git a/src/xenia/gpu/gl4/gl4_shader_translator.cc b/src/xenia/gpu/gl4/gl4_shader_translator.cc index e460ff3cb..c05ccb1d9 100644 --- a/src/xenia/gpu/gl4/gl4_shader_translator.cc +++ b/src/xenia/gpu/gl4/gl4_shader_translator.cc @@ -71,17 +71,9 @@ void GL4ShaderTranslator::Reset(GL4Shader* shader) { } std::string GL4ShaderTranslator::TranslateVertexShader( - GL4Shader* vertex_shader, - const xenos::xe_gpu_program_cntl_t& program_cntl) { + GL4Shader* vertex_shader) { Reset(vertex_shader); - // Normal shaders only, for now. - // TODO(benvanik): transform feedback/memexport. - // 0 = normal - // 2 = point size - assert_true(program_cntl.vs_export_mode == 0 || - program_cntl.vs_export_mode == 2); - // Add vertex shader input. uint32_t el_index = 0; const auto& buffer_inputs = vertex_shader->buffer_inputs(); @@ -102,8 +94,7 @@ std::string GL4ShaderTranslator::TranslateVertexShader( Append("void processVertex(const in StateData state) {\n"); // Add temporaries for any registers we may use. - uint32_t temp_regs = program_cntl.vs_regs + program_cntl.ps_regs; - for (uint32_t n = 0; n <= temp_regs; n++) { + for (uint32_t n = 0; n < 64; n++) { Append(" vec4 r%d = state.float_consts[%d];\n", n, n); } @@ -130,8 +121,7 @@ std::string GL4ShaderTranslator::TranslateVertexShader( return output_.to_string(); } -std::string GL4ShaderTranslator::TranslatePixelShader( - GL4Shader* pixel_shader, const xenos::xe_gpu_program_cntl_t& program_cntl) { +std::string GL4ShaderTranslator::TranslatePixelShader(GL4Shader* pixel_shader) { Reset(pixel_shader); // We need an input VS to make decisions here. @@ -143,8 +133,7 @@ std::string GL4ShaderTranslator::TranslatePixelShader( Append("void processFragment(const in StateData state) {\n"); // Add temporary registers. - uint32_t temp_regs = program_cntl.vs_regs + program_cntl.ps_regs; - for (uint32_t n = 0; n <= std::max(15u, temp_regs); n++) { + for (uint32_t n = 0; n < 64; n++) { Append(" vec4 r%d = state.float_consts[%d];\n", n, n + 256); } Append(" vec4 t;\n"); diff --git a/src/xenia/gpu/gl4/gl4_shader_translator.h b/src/xenia/gpu/gl4/gl4_shader_translator.h index 81aa5b65d..1533e4062 100644 --- a/src/xenia/gpu/gl4/gl4_shader_translator.h +++ b/src/xenia/gpu/gl4/gl4_shader_translator.h @@ -29,12 +29,8 @@ class GL4ShaderTranslator { GL4ShaderTranslator(); ~GL4ShaderTranslator(); - std::string TranslateVertexShader( - GL4Shader* vertex_shader, - const xenos::xe_gpu_program_cntl_t& program_cntl); - std::string TranslatePixelShader( - GL4Shader* pixel_shader, - const xenos::xe_gpu_program_cntl_t& program_cntl); + std::string TranslateVertexShader(GL4Shader* vertex_shader); + std::string TranslatePixelShader(GL4Shader* pixel_shader); protected: ShaderType shader_type_; diff --git a/src/xenia/gpu/shader.cc b/src/xenia/gpu/shader.cc index a7b6d0a8e..2ae0701dd 100644 --- a/src/xenia/gpu/shader.cc +++ b/src/xenia/gpu/shader.cc @@ -23,10 +23,7 @@ using namespace xe::gpu::xenos; Shader::Shader(ShaderType shader_type, uint64_t data_hash, const uint32_t* dword_ptr, uint32_t dword_count) - : shader_type_(shader_type), - data_hash_(data_hash), - has_prepared_(false), - is_valid_(false) { + : shader_type_(shader_type), data_hash_(data_hash) { data_.resize(dword_count); xe::copy_and_swap(data_.data(), dword_ptr, dword_count); std::memset(&alloc_counts_, 0, sizeof(alloc_counts_)); diff --git a/src/xenia/gpu/shader.h b/src/xenia/gpu/shader.h index 5b3c3232a..2ec58e46b 100644 --- a/src/xenia/gpu/shader.h +++ b/src/xenia/gpu/shader.h @@ -24,7 +24,6 @@ class Shader { virtual ~Shader(); ShaderType type() const { return shader_type_; } - bool has_prepared() const { return has_prepared_; } bool is_valid() const { return is_valid_; } const std::string& ucode_disassembly() const { return ucode_disassembly_; } const std::string& translated_disassembly() const { @@ -78,7 +77,6 @@ class Shader { bool color_targets[4]; }; const AllocCounts& alloc_counts() const { return alloc_counts_; } - const std::vector& allocs() const { return allocs_; } protected: Shader(ShaderType shader_type, uint64_t data_hash, const uint32_t* dword_ptr, @@ -93,8 +91,7 @@ class Shader { ShaderType shader_type_; uint64_t data_hash_; std::vector data_; - bool has_prepared_; - bool is_valid_; + bool is_valid_ = false; std::string ucode_disassembly_; std::string translated_disassembly_; diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index 555bf4450..d00932033 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -477,9 +477,9 @@ TraceViewer::ShaderDisplayType TraceViewer::DrawShaderTypeUI() { void TraceViewer::DrawShaderUI(Shader* shader, ShaderDisplayType display_type) { // Must be prepared for advanced display modes. if (display_type != ShaderDisplayType::kUcode) { - if (!shader->has_prepared()) { + if (!shader->is_valid()) { ImGui::TextColored(kColorError, - "ERROR: shader not prepared (not used this frame?)"); + "ERROR: shader error during parsing/translation"); return; } }