[D3D12] Quad list geometry shader

This commit is contained in:
Triang3l 2018-08-26 19:51:20 +03:00
parent 2c24622bdb
commit 592873cf9f
5 changed files with 54 additions and 42 deletions

View File

@ -948,6 +948,9 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
case PrimitiveType::kTriangleStrip: case PrimitiveType::kTriangleStrip:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
break; break;
case PrimitiveType::kQuadList:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
break;
default: default:
return false; return false;
} }

View File

@ -27,6 +27,7 @@ namespace gpu {
namespace d3d12 { namespace d3d12 {
// Generated with `xb buildhlsl`. // Generated with `xb buildhlsl`.
#include "xenia/gpu/d3d12/shaders/bin/primitive_quad_list_gs.h"
#include "xenia/gpu/d3d12/shaders/bin/primitive_rectangle_list_gs.h" #include "xenia/gpu/d3d12/shaders/bin/primitive_rectangle_list_gs.h"
PipelineCache::PipelineCache(D3D12CommandProcessor* command_processor, PipelineCache::PipelineCache(D3D12CommandProcessor* command_processor,
@ -275,15 +276,26 @@ PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages(
dirty |= regs.pixel_shader != pixel_shader; dirty |= regs.pixel_shader != pixel_shader;
regs.vertex_shader = vertex_shader; regs.vertex_shader = vertex_shader;
regs.pixel_shader = pixel_shader; regs.pixel_shader = pixel_shader;
// Points are emulated via a geometry shader because Direct3D 10+ doesn't // This topology type is before the geometry shader stage.
// support point sizes other than 1. D3D12_PRIMITIVE_TOPOLOGY_TYPE primitive_topology_type;
bool primitive_topology_is_line = switch (primitive_type) {
primitive_type == PrimitiveType::kLineList || case PrimitiveType::kPointList:
primitive_type == PrimitiveType::kLineStrip || primitive_topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
primitive_type == PrimitiveType::kLineLoop || break;
primitive_type == PrimitiveType::k2DLineStrip; case PrimitiveType::kLineList:
dirty |= regs.primitive_topology_is_line != primitive_topology_is_line; case PrimitiveType::kLineStrip:
if (primitive_type == PrimitiveType::kRectangleList) { case PrimitiveType::kLineLoop:
// Quads are emulated as line lists with adjacency.
case PrimitiveType::kQuadList:
case PrimitiveType::k2DLineStrip:
primitive_topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
break;
default:
primitive_topology_type = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
};
dirty |= regs.primitive_topology_type != primitive_topology_type;
if (primitive_type == PrimitiveType::kRectangleList ||
primitive_type == PrimitiveType::kQuadList) {
dirty |= regs.geometry_shader_primitive_type != primitive_type; dirty |= regs.geometry_shader_primitive_type != primitive_type;
regs.geometry_shader_primitive_type = primitive_type; regs.geometry_shader_primitive_type = primitive_type;
} else { } else {
@ -318,14 +330,16 @@ PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages(
update_desc_.GS.pShaderBytecode = primitive_rectangle_list_gs; update_desc_.GS.pShaderBytecode = primitive_rectangle_list_gs;
update_desc_.GS.BytecodeLength = sizeof(primitive_rectangle_list_gs); update_desc_.GS.BytecodeLength = sizeof(primitive_rectangle_list_gs);
break; break;
case PrimitiveType::kQuadList:
update_desc_.GS.pShaderBytecode = primitive_quad_list_gs;
update_desc_.GS.BytecodeLength = sizeof(primitive_quad_list_gs);
break;
default: default:
// TODO(Triang3l): More geometry shaders for various primitive types. // TODO(Triang3l): More geometry shaders for various primitive types.
update_desc_.GS.pShaderBytecode = nullptr; update_desc_.GS.pShaderBytecode = nullptr;
update_desc_.GS.BytecodeLength = 0; update_desc_.GS.BytecodeLength = 0;
} }
update_desc_.PrimitiveTopologyType = update_desc_.PrimitiveTopologyType = primitive_topology_type;
primitive_topology_is_line ? D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE
: D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
return UpdateStatus::kMismatch; return UpdateStatus::kMismatch;
} }

View File

@ -115,7 +115,7 @@ class PipelineCache {
struct UpdateShaderStagesRegisters { struct UpdateShaderStagesRegisters {
D3D12Shader* vertex_shader; D3D12Shader* vertex_shader;
D3D12Shader* pixel_shader; D3D12Shader* pixel_shader;
bool primitive_topology_is_line; D3D12_PRIMITIVE_TOPOLOGY_TYPE primitive_topology_type;
// Primitive type if it needs a geometry shader, or kNone. // Primitive type if it needs a geometry shader, or kNone.
PrimitiveType geometry_shader_primitive_type; PrimitiveType geometry_shader_primitive_type;

View File

@ -0,0 +1,15 @@
struct XeVertex {
float4 interpolators[16] : TEXCOORD;
float4 position : SV_Position;
float point_size : PSIZE;
};
[maxvertexcount(4)]
void main(lineadj XeVertex xe_in[4],
inout TriangleStream<XeVertex> xe_stream) {
xe_stream.Append(xe_in[0]);
xe_stream.Append(xe_in[1]);
xe_stream.Append(xe_in[3]);
xe_stream.Append(xe_in[2]);
xe_stream.RestartStrip();
}

View File

@ -5,21 +5,13 @@ struct XeVertex {
}; };
[maxvertexcount(6)] [maxvertexcount(6)]
void main(triangle XeVertex xe_in[3], inout TriangleStream<XeVertex> xe_stream) { void main(triangle XeVertex xe_in[3],
inout TriangleStream<XeVertex> xe_stream) {
XeVertex xe_out; XeVertex xe_out;
xe_out.interpolators = xe_in[0].interpolators; xe_stream.Append(xe_in[0]);
xe_out.position = xe_in[0].position; xe_stream.Append(xe_in[1]);
xe_out.point_size = xe_in[0].point_size; xe_stream.Append(xe_in[2]);
xe_stream.Append(xe_out);
xe_out.interpolators = xe_in[1].interpolators;
xe_out.position = xe_in[1].position;
xe_out.point_size = xe_in[1].point_size;
xe_stream.Append(xe_out);
xe_out.interpolators = xe_in[2].interpolators;
xe_out.position = xe_in[2].position;
xe_out.point_size = xe_in[2].point_size;
xe_stream.Append(xe_out);
xe_stream.RestartStrip(); xe_stream.RestartStrip();
// Most games use a left-aligned form. // Most games use a left-aligned form.
@ -38,14 +30,8 @@ void main(triangle XeVertex xe_in[3], inout TriangleStream<XeVertex> xe_stream)
// | // | 2: 1,-1 // | // | 2: 1,-1
// | - | 3: [ 1, 1 ] // | - | 3: [ 1, 1 ]
// 1 ------[3] // 1 ------[3]
xe_out.interpolators = xe_in[2].interpolators; xe_stream.Append(xe_in[2]);
xe_out.position = xe_in[2].position; xe_stream.Append(xe_in[1]);
xe_out.point_size = xe_in[2].point_size;
xe_stream.Append(xe_out);
xe_out.interpolators = xe_in[1].interpolators;
xe_out.position = xe_in[1].position;
xe_out.point_size = xe_in[1].point_size;
xe_stream.Append(xe_out);
[unroll] for (int i = 0; i < 16; ++i) { [unroll] for (int i = 0; i < 16; ++i) {
xe_out.interpolators[i] = xe_in[1].interpolators[i] - xe_out.interpolators[i] = xe_in[1].interpolators[i] -
xe_in[0].interpolators[i] + xe_in[0].interpolators[i] +
@ -61,14 +47,8 @@ void main(triangle XeVertex xe_in[3], inout TriangleStream<XeVertex> xe_stream)
// | \\ | 2: 1, 1 // | \\ | 2: 1, 1
// | - | 3: [-1, 1 ] // | - | 3: [-1, 1 ]
// [3] ----- 2 // [3] ----- 2
xe_out.interpolators = xe_in[0].interpolators; xe_stream.Append(xe_in[0]);
xe_out.position = xe_in[0].position; xe_stream.Append(xe_in[2]);
xe_out.point_size = xe_in[0].point_size;
xe_stream.Append(xe_out);
xe_out.interpolators = xe_in[2].interpolators;
xe_out.position = xe_in[2].position;
xe_out.point_size = xe_in[2].point_size;
xe_stream.Append(xe_out);
[unroll] for (int i = 0; i < 16; ++i) { [unroll] for (int i = 0; i < 16; ++i) {
xe_out.interpolators[i] = xe_in[0].interpolators[i] - xe_out.interpolators[i] = xe_in[0].interpolators[i] -
xe_in[1].interpolators[i] + xe_in[1].interpolators[i] +