[D3D12] Quad list geometry shader
This commit is contained in:
parent
2c24622bdb
commit
592873cf9f
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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] +
|
||||||
|
|
Loading…
Reference in New Issue