Unplumbing program_cntl and simplifying shader loading.
This commit is contained in:
parent
6a546ebe4d
commit
89172da4b7
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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_));
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue