Special quad list line geometry shader.

Fixes #174.
This commit is contained in:
Ben Vanik 2015-03-03 20:31:05 -08:00
parent 41174b0e64
commit 4b5f77bde4
2 changed files with 61 additions and 4 deletions

View File

@ -45,7 +45,10 @@ CommandProcessor::CachedPipeline::CachedPipeline()
CommandProcessor::CachedPipeline::~CachedPipeline() { CommandProcessor::CachedPipeline::~CachedPipeline() {
glDeleteProgramPipelines(1, &handles.default_pipeline); glDeleteProgramPipelines(1, &handles.default_pipeline);
glDeleteProgramPipelines(1, &handles.point_list_pipeline);
glDeleteProgramPipelines(1, &handles.rect_list_pipeline); glDeleteProgramPipelines(1, &handles.rect_list_pipeline);
glDeleteProgramPipelines(1, &handles.quad_list_pipeline);
glDeleteProgramPipelines(1, &handles.line_quad_list_pipeline);
} }
CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system) CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system)
@ -364,11 +367,40 @@ bool CommandProcessor::SetupGL() {
" }\n" " }\n"
" EndPrimitive();\n" " EndPrimitive();\n"
"}\n"; "}\n";
std::string line_quad_list_shader =
geometry_header +
"layout(lines_adjacency) in;\n"
"layout(line_strip, max_vertices = 5) out;\n"
"void main() {\n"
" gl_Position = gl_in[0].gl_Position;\n"
" gl_PointSize = gl_in[0].gl_PointSize;\n"
" out_vtx = in_vtx[0];\n"
" EmitVertex();\n"
" gl_Position = gl_in[1].gl_Position;\n"
" gl_PointSize = gl_in[1].gl_PointSize;\n"
" out_vtx = in_vtx[1];\n"
" EmitVertex();\n"
" gl_Position = gl_in[2].gl_Position;\n"
" gl_PointSize = gl_in[2].gl_PointSize;\n"
" out_vtx = in_vtx[2];\n"
" EmitVertex();\n"
" gl_Position = gl_in[3].gl_Position;\n"
" gl_PointSize = gl_in[3].gl_PointSize;\n"
" out_vtx = in_vtx[3];\n"
" EmitVertex();\n"
" gl_Position = gl_in[0].gl_Position;\n"
" gl_PointSize = gl_in[0].gl_PointSize;\n"
" out_vtx = in_vtx[0];\n"
" EmitVertex();\n"
" EndPrimitive();\n"
"}\n";
point_list_geometry_program_ = CreateGeometryProgram(point_list_shader); point_list_geometry_program_ = CreateGeometryProgram(point_list_shader);
rect_list_geometry_program_ = CreateGeometryProgram(rect_list_shader); rect_list_geometry_program_ = CreateGeometryProgram(rect_list_shader);
quad_list_geometry_program_ = CreateGeometryProgram(quad_list_shader); quad_list_geometry_program_ = CreateGeometryProgram(quad_list_shader);
line_quad_list_geometry_program_ =
CreateGeometryProgram(line_quad_list_shader);
if (!point_list_geometry_program_ || !rect_list_geometry_program_ || if (!point_list_geometry_program_ || !rect_list_geometry_program_ ||
!quad_list_geometry_program_) { !quad_list_geometry_program_ || !line_quad_list_geometry_program_) {
return false; return false;
} }
@ -401,6 +433,7 @@ void CommandProcessor::ShutdownGL() {
glDeleteProgram(point_list_geometry_program_); glDeleteProgram(point_list_geometry_program_);
glDeleteProgram(rect_list_geometry_program_); glDeleteProgram(rect_list_geometry_program_);
glDeleteProgram(quad_list_geometry_program_); glDeleteProgram(quad_list_geometry_program_);
glDeleteProgram(line_quad_list_geometry_program_);
texture_cache_.Shutdown(); texture_cache_.Shutdown();
draw_batcher_.Shutdown(); draw_batcher_.Shutdown();
scratch_buffer_.Shutdown(); scratch_buffer_.Shutdown();
@ -1431,6 +1464,8 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateShaders(
auto& regs = update_shaders_regs_; auto& regs = update_shaders_regs_;
bool dirty = false; bool dirty = false;
dirty |=
SetShadowRegister(regs.pa_su_sc_mode_cntl, XE_GPU_REG_PA_SU_SC_MODE_CNTL);
dirty |= SetShadowRegister(regs.sq_program_cntl, XE_GPU_REG_SQ_PROGRAM_CNTL); dirty |= SetShadowRegister(regs.sq_program_cntl, XE_GPU_REG_SQ_PROGRAM_CNTL);
dirty |= regs.vertex_shader != active_vertex_shader_; dirty |= regs.vertex_shader != active_vertex_shader_;
dirty |= regs.pixel_shader != active_pixel_shader_; dirty |= regs.pixel_shader != active_pixel_shader_;
@ -1489,7 +1524,7 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateShaders(
} }
if (!cached_pipeline->handles.default_pipeline) { if (!cached_pipeline->handles.default_pipeline) {
// Perhaps it's a bit wasteful to do all of these, but oh well. // Perhaps it's a bit wasteful to do all of these, but oh well.
GLuint pipelines[4]; GLuint pipelines[5];
glCreateProgramPipelines(GLsizei(poly::countof(pipelines)), pipelines); glCreateProgramPipelines(GLsizei(poly::countof(pipelines)), pipelines);
glUseProgramStages(pipelines[0], GL_VERTEX_SHADER_BIT, vertex_program); glUseProgramStages(pipelines[0], GL_VERTEX_SHADER_BIT, vertex_program);
@ -1514,6 +1549,12 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateShaders(
glUseProgramStages(pipelines[3], GL_FRAGMENT_SHADER_BIT, fragment_program); glUseProgramStages(pipelines[3], GL_FRAGMENT_SHADER_BIT, fragment_program);
cached_pipeline->handles.quad_list_pipeline = pipelines[3]; cached_pipeline->handles.quad_list_pipeline = pipelines[3];
glUseProgramStages(pipelines[4], GL_VERTEX_SHADER_BIT, vertex_program);
glUseProgramStages(pipelines[4], GL_GEOMETRY_SHADER_BIT,
line_quad_list_geometry_program_);
glUseProgramStages(pipelines[4], GL_FRAGMENT_SHADER_BIT, fragment_program);
cached_pipeline->handles.line_quad_list_pipeline = pipelines[4];
// This can be set once, as the buffer never changes. // This can be set once, as the buffer never changes.
if (has_bindless_vbos_) { if (has_bindless_vbos_) {
glBindVertexArray(active_vertex_shader_->vao()); glBindVertexArray(active_vertex_shader_->vao());
@ -1526,6 +1567,14 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateShaders(
} }
} }
bool line_mode = false;
if (((regs.pa_su_sc_mode_cntl >> 3) & 0x3) != 0) {
uint32_t front_poly_mode = (regs.pa_su_sc_mode_cntl >> 5) & 0x7;
if (front_poly_mode == 1) {
line_mode = true;
}
}
GLuint pipeline = cached_pipeline->handles.default_pipeline; GLuint pipeline = cached_pipeline->handles.default_pipeline;
switch (regs.prim_type) { switch (regs.prim_type) {
case PrimitiveType::kPointList: case PrimitiveType::kPointList:
@ -1534,9 +1583,14 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateShaders(
case PrimitiveType::kRectangleList: case PrimitiveType::kRectangleList:
pipeline = cached_pipeline->handles.rect_list_pipeline; pipeline = cached_pipeline->handles.rect_list_pipeline;
break; break;
case PrimitiveType::kQuadList: case PrimitiveType::kQuadList: {
pipeline = cached_pipeline->handles.quad_list_pipeline; if (line_mode) {
pipeline = cached_pipeline->handles.line_quad_list_pipeline;
} else {
pipeline = cached_pipeline->handles.quad_list_pipeline;
}
break; break;
}
} }
draw_batcher_.ReconfigurePipeline(active_vertex_shader_, active_pixel_shader_, draw_batcher_.ReconfigurePipeline(active_vertex_shader_, active_pixel_shader_,

View File

@ -122,6 +122,7 @@ class CommandProcessor {
GLuint point_list_pipeline; GLuint point_list_pipeline;
GLuint rect_list_pipeline; GLuint rect_list_pipeline;
GLuint quad_list_pipeline; GLuint quad_list_pipeline;
GLuint line_quad_list_pipeline;
// TODO(benvanik): others with geometry shaders. // TODO(benvanik): others with geometry shaders.
} handles; } handles;
}; };
@ -262,6 +263,7 @@ class CommandProcessor {
GLuint point_list_geometry_program_; GLuint point_list_geometry_program_;
GLuint rect_list_geometry_program_; GLuint rect_list_geometry_program_;
GLuint quad_list_geometry_program_; GLuint quad_list_geometry_program_;
GLuint line_quad_list_geometry_program_;
struct { struct {
xenos::IndexFormat format; xenos::IndexFormat format;
xenos::Endian endianness; xenos::Endian endianness;
@ -323,6 +325,7 @@ class CommandProcessor {
} update_depth_stencil_state_regs_; } update_depth_stencil_state_regs_;
struct UpdateShadersRegisters { struct UpdateShadersRegisters {
PrimitiveType prim_type; PrimitiveType prim_type;
uint32_t pa_su_sc_mode_cntl;
uint32_t sq_program_cntl; uint32_t sq_program_cntl;
GL4Shader* vertex_shader; GL4Shader* vertex_shader;
GL4Shader* pixel_shader; GL4Shader* pixel_shader;