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;
} else {
// 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,
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;
}

View File

@ -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;

View File

@ -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();

View File

@ -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");

View File

@ -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_;

View File

@ -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_));

View File

@ -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<ucode::instr_cf_alloc_t>& 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<uint32_t> data_;
bool has_prepared_;
bool is_valid_;
bool is_valid_ = false;
std::string ucode_disassembly_;
std::string translated_disassembly_;

View File

@ -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;
}
}