Unplumbing program_cntl and simplifying shader loading.

This commit is contained in:
Ben Vanik 2015-11-24 20:24:35 -08:00
parent 6a546ebe4d
commit 89172da4b7
8 changed files with 38 additions and 64 deletions

View File

@ -482,13 +482,20 @@ Shader* GL4CommandProcessor::LoadShader(ShaderType shader_type,
shader_ptr = it->second; shader_ptr = it->second;
} else { } else {
// Not found in cache. // Not found in cache.
// No translation is performed here, as it depends on program_cntl.
auto shader = std::make_unique<GL4Shader>(shader_type, hash, host_address, auto shader = std::make_unique<GL4Shader>(shader_type, hash, host_address,
dword_count); dword_count);
shader_ptr = shader.get(); shader_ptr = shader.get();
shader_cache_.insert({hash, shader_ptr}); shader_cache_.insert({hash, shader_ptr});
all_shaders_.emplace_back(std::move(shader)); 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", XELOGGPU("Set %s shader at %0.8X (%db):\n%s",
shader_type == ShaderType::kVertex ? "vertex" : "pixel", shader_type == ShaderType::kVertex ? "vertex" : "pixel",
guest_address, dword_count * 4, guest_address, dword_count * 4,
@ -626,24 +633,19 @@ GL4CommandProcessor::UpdateStatus GL4CommandProcessor::UpdateShaders(
xe_gpu_program_cntl_t program_cntl; xe_gpu_program_cntl_t program_cntl;
program_cntl.dword_0 = regs.sq_program_cntl; program_cntl.dword_0 = regs.sq_program_cntl;
if (!regs.vertex_shader->has_prepared()) {
if (!regs.vertex_shader->PrepareVertexShader(&shader_translator_, // Normal vertex shaders only, for now.
program_cntl)) { // TODO(benvanik): transform feedback/memexport.
XELOGE("Unable to prepare vertex shader"); // 0 = normal
return UpdateStatus::kError; // 2 = point size
} assert_true(program_cntl.vs_export_mode == 0 ||
} else if (!regs.vertex_shader->is_valid()) { program_cntl.vs_export_mode == 2);
if (!regs.vertex_shader->is_valid()) {
XELOGE("Vertex shader invalid"); XELOGE("Vertex shader invalid");
return UpdateStatus::kError; return UpdateStatus::kError;
} }
if (!regs.pixel_shader->is_valid()) {
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()) {
XELOGE("Pixel shader invalid"); XELOGE("Pixel shader invalid");
return UpdateStatus::kError; return UpdateStatus::kError;
} }

View File

@ -198,13 +198,11 @@ bool GL4Shader::PrepareVertexArrayObject() {
return true; return true;
} }
bool GL4Shader::PrepareVertexShader( bool GL4Shader::PrepareVertexShader(GL4ShaderTranslator* shader_translator) {
GL4ShaderTranslator* shader_translator, if (is_valid_) {
const xenos::xe_gpu_program_cntl_t& program_cntl) {
if (has_prepared_) {
return is_valid_; return is_valid_;
} }
has_prepared_ = true; is_valid_ = false;
// Build static vertex array descriptor. // Build static vertex array descriptor.
if (!PrepareVertexArrayObject()) { if (!PrepareVertexArrayObject()) {
@ -253,7 +251,7 @@ bool GL4Shader::PrepareVertexShader(
GetFooter(); GetFooter();
std::string translated_source = std::string translated_source =
shader_translator->TranslateVertexShader(this, program_cntl); shader_translator->TranslateVertexShader(this);
if (translated_source.empty()) { if (translated_source.empty()) {
XELOGE("Vertex shader failed translation"); XELOGE("Vertex shader failed translation");
return false; return false;
@ -268,13 +266,11 @@ bool GL4Shader::PrepareVertexShader(
return true; return true;
} }
bool GL4Shader::PreparePixelShader( bool GL4Shader::PreparePixelShader(GL4ShaderTranslator* shader_translator) {
GL4ShaderTranslator* shader_translator, if (is_valid_) {
const xenos::xe_gpu_program_cntl_t& program_cntl) {
if (has_prepared_) {
return is_valid_; return is_valid_;
} }
has_prepared_ = true; is_valid_ = false;
std::string source = std::string source =
GetHeader() + GetHeader() +
@ -306,8 +302,7 @@ bool GL4Shader::PreparePixelShader(
"}\n" + "}\n" +
GetFooter(); GetFooter();
std::string translated_source = std::string translated_source = shader_translator->TranslatePixelShader(this);
shader_translator->TranslatePixelShader(this, program_cntl);
if (translated_source.empty()) { if (translated_source.empty()) {
XELOGE("Pixel shader failed translation"); XELOGE("Pixel shader failed translation");
return false; return false;

View File

@ -30,10 +30,8 @@ class GL4Shader : public Shader {
GLuint program() const { return program_; } GLuint program() const { return program_; }
GLuint vao() const { return vao_; } GLuint vao() const { return vao_; }
bool PrepareVertexShader(GL4ShaderTranslator* shader_translator, bool PrepareVertexShader(GL4ShaderTranslator* shader_translator);
const xenos::xe_gpu_program_cntl_t& program_cntl); bool PreparePixelShader(GL4ShaderTranslator* shader_translator);
bool PreparePixelShader(GL4ShaderTranslator* shader_translator,
const xenos::xe_gpu_program_cntl_t& program_cntl);
protected: protected:
std::string GetHeader(); std::string GetHeader();

View File

@ -71,17 +71,9 @@ void GL4ShaderTranslator::Reset(GL4Shader* shader) {
} }
std::string GL4ShaderTranslator::TranslateVertexShader( std::string GL4ShaderTranslator::TranslateVertexShader(
GL4Shader* vertex_shader, GL4Shader* vertex_shader) {
const xenos::xe_gpu_program_cntl_t& program_cntl) {
Reset(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. // Add vertex shader input.
uint32_t el_index = 0; uint32_t el_index = 0;
const auto& buffer_inputs = vertex_shader->buffer_inputs(); const auto& buffer_inputs = vertex_shader->buffer_inputs();
@ -102,8 +94,7 @@ std::string GL4ShaderTranslator::TranslateVertexShader(
Append("void processVertex(const in StateData state) {\n"); Append("void processVertex(const in StateData state) {\n");
// Add temporaries for any registers we may use. // 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 < 64; n++) {
for (uint32_t n = 0; n <= temp_regs; n++) {
Append(" vec4 r%d = state.float_consts[%d];\n", n, n); Append(" vec4 r%d = state.float_consts[%d];\n", n, n);
} }
@ -130,8 +121,7 @@ std::string GL4ShaderTranslator::TranslateVertexShader(
return output_.to_string(); return output_.to_string();
} }
std::string GL4ShaderTranslator::TranslatePixelShader( std::string GL4ShaderTranslator::TranslatePixelShader(GL4Shader* pixel_shader) {
GL4Shader* pixel_shader, const xenos::xe_gpu_program_cntl_t& program_cntl) {
Reset(pixel_shader); Reset(pixel_shader);
// We need an input VS to make decisions here. // 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"); Append("void processFragment(const in StateData state) {\n");
// Add temporary registers. // Add temporary registers.
uint32_t temp_regs = program_cntl.vs_regs + program_cntl.ps_regs; for (uint32_t n = 0; n < 64; n++) {
for (uint32_t n = 0; n <= std::max(15u, temp_regs); n++) {
Append(" vec4 r%d = state.float_consts[%d];\n", n, n + 256); Append(" vec4 r%d = state.float_consts[%d];\n", n, n + 256);
} }
Append(" vec4 t;\n"); Append(" vec4 t;\n");

View File

@ -29,12 +29,8 @@ class GL4ShaderTranslator {
GL4ShaderTranslator(); GL4ShaderTranslator();
~GL4ShaderTranslator(); ~GL4ShaderTranslator();
std::string TranslateVertexShader( std::string TranslateVertexShader(GL4Shader* vertex_shader);
GL4Shader* vertex_shader, std::string TranslatePixelShader(GL4Shader* pixel_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);
protected: protected:
ShaderType shader_type_; ShaderType shader_type_;

View File

@ -23,10 +23,7 @@ using namespace xe::gpu::xenos;
Shader::Shader(ShaderType shader_type, uint64_t data_hash, Shader::Shader(ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count) const uint32_t* dword_ptr, uint32_t dword_count)
: shader_type_(shader_type), : shader_type_(shader_type), data_hash_(data_hash) {
data_hash_(data_hash),
has_prepared_(false),
is_valid_(false) {
data_.resize(dword_count); data_.resize(dword_count);
xe::copy_and_swap(data_.data(), dword_ptr, dword_count); xe::copy_and_swap(data_.data(), dword_ptr, dword_count);
std::memset(&alloc_counts_, 0, sizeof(alloc_counts_)); std::memset(&alloc_counts_, 0, sizeof(alloc_counts_));

View File

@ -24,7 +24,6 @@ class Shader {
virtual ~Shader(); virtual ~Shader();
ShaderType type() const { return shader_type_; } ShaderType type() const { return shader_type_; }
bool has_prepared() const { return has_prepared_; }
bool is_valid() const { return is_valid_; } bool is_valid() const { return is_valid_; }
const std::string& ucode_disassembly() const { return ucode_disassembly_; } const std::string& ucode_disassembly() const { return ucode_disassembly_; }
const std::string& translated_disassembly() const { const std::string& translated_disassembly() const {
@ -78,7 +77,6 @@ class Shader {
bool color_targets[4]; bool color_targets[4];
}; };
const AllocCounts& alloc_counts() const { return alloc_counts_; } const AllocCounts& alloc_counts() const { return alloc_counts_; }
const std::vector<ucode::instr_cf_alloc_t>& allocs() const { return allocs_; }
protected: protected:
Shader(ShaderType shader_type, uint64_t data_hash, const uint32_t* dword_ptr, Shader(ShaderType shader_type, uint64_t data_hash, const uint32_t* dword_ptr,
@ -93,8 +91,7 @@ class Shader {
ShaderType shader_type_; ShaderType shader_type_;
uint64_t data_hash_; uint64_t data_hash_;
std::vector<uint32_t> data_; std::vector<uint32_t> data_;
bool has_prepared_; bool is_valid_ = false;
bool is_valid_;
std::string ucode_disassembly_; std::string ucode_disassembly_;
std::string translated_disassembly_; std::string translated_disassembly_;

View File

@ -477,9 +477,9 @@ TraceViewer::ShaderDisplayType TraceViewer::DrawShaderTypeUI() {
void TraceViewer::DrawShaderUI(Shader* shader, ShaderDisplayType display_type) { void TraceViewer::DrawShaderUI(Shader* shader, ShaderDisplayType display_type) {
// Must be prepared for advanced display modes. // Must be prepared for advanced display modes.
if (display_type != ShaderDisplayType::kUcode) { if (display_type != ShaderDisplayType::kUcode) {
if (!shader->has_prepared()) { if (!shader->is_valid()) {
ImGui::TextColored(kColorError, ImGui::TextColored(kColorError,
"ERROR: shader not prepared (not used this frame?)"); "ERROR: shader error during parsing/translation");
return; return;
} }
} }