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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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_));
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue