Unplumbing program_cntl and simplifying shader loading.
This commit is contained in:
@@ -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_;
|
||||
|
||||
Reference in New Issue
Block a user