[D3D12] Optional non-GS path for quads for PIX
This commit is contained in:
parent
eaefc3862f
commit
4a3245650f
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include "xenia/gpu/d3d12/primitive_converter.h"
|
#include "xenia/gpu/d3d12/primitive_converter.h"
|
||||||
|
|
||||||
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "xenia/base/assert.h"
|
#include "xenia/base/assert.h"
|
||||||
|
@ -20,6 +22,12 @@
|
||||||
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
|
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
|
||||||
#include "xenia/ui/d3d12/d3d12_util.h"
|
#include "xenia/ui/d3d12/d3d12_util.h"
|
||||||
|
|
||||||
|
DEFINE_bool(d3d12_convert_quads_to_triangles, false,
|
||||||
|
"Convert quad lists to triangle lists on the CPU instead of using "
|
||||||
|
"a geometry shader. Not recommended for playing, for debugging "
|
||||||
|
"primarily (because PIX fails to display vertices when a geometry "
|
||||||
|
"shader is used).");
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
@ -27,6 +35,8 @@ namespace d3d12 {
|
||||||
constexpr uint32_t PrimitiveConverter::kMaxNonIndexedVertices;
|
constexpr uint32_t PrimitiveConverter::kMaxNonIndexedVertices;
|
||||||
constexpr uint32_t PrimitiveConverter::kStaticIBTriangleFanOffset;
|
constexpr uint32_t PrimitiveConverter::kStaticIBTriangleFanOffset;
|
||||||
constexpr uint32_t PrimitiveConverter::kStaticIBTriangleFanCount;
|
constexpr uint32_t PrimitiveConverter::kStaticIBTriangleFanCount;
|
||||||
|
constexpr uint32_t PrimitiveConverter::kStaticIBQuadOffset;
|
||||||
|
constexpr uint32_t PrimitiveConverter::kStaticIBQuadCount;
|
||||||
constexpr uint32_t PrimitiveConverter::kStaticIBTotalCount;
|
constexpr uint32_t PrimitiveConverter::kStaticIBTotalCount;
|
||||||
|
|
||||||
PrimitiveConverter::PrimitiveConverter(D3D12CommandProcessor* command_processor,
|
PrimitiveConverter::PrimitiveConverter(D3D12CommandProcessor* command_processor,
|
||||||
|
@ -81,12 +91,22 @@ bool PrimitiveConverter::Initialize() {
|
||||||
// Triangle fans as triangle lists.
|
// Triangle fans as triangle lists.
|
||||||
// https://docs.microsoft.com/en-us/windows/desktop/direct3d9/triangle-fans
|
// https://docs.microsoft.com/en-us/windows/desktop/direct3d9/triangle-fans
|
||||||
// Ordered as (v1, v2, v0), (v2, v3, v0).
|
// Ordered as (v1, v2, v0), (v2, v3, v0).
|
||||||
uint16_t* static_ib_data_triangle_fan =
|
uint16_t* static_ib_data_pointer =
|
||||||
&static_ib_data[kStaticIBTriangleFanOffset];
|
&static_ib_data[kStaticIBTriangleFanOffset];
|
||||||
for (uint32_t i = 2; i < kMaxNonIndexedVertices; ++i) {
|
for (uint32_t i = 2; i < kMaxNonIndexedVertices; ++i) {
|
||||||
*(static_ib_data_triangle_fan++) = i - 1;
|
*(static_ib_data_pointer++) = i - 1;
|
||||||
*(static_ib_data_triangle_fan++) = i;
|
*(static_ib_data_pointer++) = i;
|
||||||
*(static_ib_data_triangle_fan++) = 0;
|
*(static_ib_data_pointer++) = 0;
|
||||||
|
}
|
||||||
|
static_ib_data_pointer = &static_ib_data[kStaticIBQuadOffset];
|
||||||
|
for (uint32_t i = 0; i < (kMaxNonIndexedVertices >> 2); ++i) {
|
||||||
|
uint32_t quad_index = i << 2;
|
||||||
|
*(static_ib_data_pointer++) = quad_index;
|
||||||
|
*(static_ib_data_pointer++) = quad_index + 1;
|
||||||
|
*(static_ib_data_pointer++) = quad_index + 2;
|
||||||
|
*(static_ib_data_pointer++) = quad_index;
|
||||||
|
*(static_ib_data_pointer++) = quad_index + 2;
|
||||||
|
*(static_ib_data_pointer++) = quad_index + 3;
|
||||||
}
|
}
|
||||||
static_ib_upload_->Unmap(0, nullptr);
|
static_ib_upload_->Unmap(0, nullptr);
|
||||||
// Not uploaded yet.
|
// Not uploaded yet.
|
||||||
|
@ -155,6 +175,11 @@ PrimitiveType PrimitiveConverter::GetReplacementPrimitiveType(
|
||||||
return PrimitiveType::kTriangleList;
|
return PrimitiveType::kTriangleList;
|
||||||
case PrimitiveType::kLineLoop:
|
case PrimitiveType::kLineLoop:
|
||||||
return PrimitiveType::kLineStrip;
|
return PrimitiveType::kLineStrip;
|
||||||
|
case PrimitiveType::kQuadList:
|
||||||
|
if (FLAGS_d3d12_convert_quads_to_triangles) {
|
||||||
|
return PrimitiveType::kTriangleList;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -187,6 +212,10 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
|
||||||
if (!reset || reset_index == reset_index_host) {
|
if (!reset || reset_index == reset_index_host) {
|
||||||
return ConversionResult::kConversionNotNeeded;
|
return ConversionResult::kConversionNotNeeded;
|
||||||
}
|
}
|
||||||
|
} else if (source_type == PrimitiveType::kQuadList) {
|
||||||
|
if (!FLAGS_d3d12_convert_quads_to_triangles) {
|
||||||
|
return ConversionResult::kConversionNotNeeded;
|
||||||
|
}
|
||||||
} else if (source_type != PrimitiveType::kTriangleFan &&
|
} else if (source_type != PrimitiveType::kTriangleFan &&
|
||||||
source_type != PrimitiveType::kLineLoop) {
|
source_type != PrimitiveType::kLineLoop) {
|
||||||
return ConversionResult::kConversionNotNeeded;
|
return ConversionResult::kConversionNotNeeded;
|
||||||
|
@ -201,6 +230,8 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
|
||||||
if (source_type == PrimitiveType::kLineStrip ||
|
if (source_type == PrimitiveType::kLineStrip ||
|
||||||
source_type == PrimitiveType::kLineLoop) {
|
source_type == PrimitiveType::kLineLoop) {
|
||||||
index_count_min = 2;
|
index_count_min = 2;
|
||||||
|
} else if (source_type == PrimitiveType::kQuadList) {
|
||||||
|
index_count_min = 4;
|
||||||
} else {
|
} else {
|
||||||
index_count_min = 3;
|
index_count_min = 3;
|
||||||
}
|
}
|
||||||
|
@ -404,6 +435,9 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
|
||||||
} else {
|
} else {
|
||||||
converted_index_count = index_count + 1;
|
converted_index_count = index_count + 1;
|
||||||
}
|
}
|
||||||
|
} else if (source_type == PrimitiveType::kQuadList) {
|
||||||
|
conversion_needed = true;
|
||||||
|
converted_index_count = (index_count >> 2) * 6;
|
||||||
}
|
}
|
||||||
converted_indices.converted_index_count = converted_index_count;
|
converted_indices.converted_index_count = converted_index_count;
|
||||||
|
|
||||||
|
@ -598,6 +632,31 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (source_type == PrimitiveType::kQuadList) {
|
||||||
|
uint32_t quad_count = index_count >> 4;
|
||||||
|
if (index_format == IndexFormat::kInt32) {
|
||||||
|
uint32_t* target_32 = reinterpret_cast<uint32_t*>(target);
|
||||||
|
for (uint32_t i = 0; i < quad_count; ++i) {
|
||||||
|
uint32_t quad_index = i << 2;
|
||||||
|
*(target_32++) = source_32[quad_index];
|
||||||
|
*(target_32++) = source_32[quad_index + 1];
|
||||||
|
*(target_32++) = source_32[quad_index + 2];
|
||||||
|
*(target_32++) = source_32[quad_index];
|
||||||
|
*(target_32++) = source_32[quad_index + 2];
|
||||||
|
*(target_32++) = source_32[quad_index + 3];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint16_t* target_16 = reinterpret_cast<uint16_t*>(target);
|
||||||
|
for (uint32_t i = 0; i < quad_count; ++i) {
|
||||||
|
uint32_t quad_index = i << 2;
|
||||||
|
*(target_16++) = source_16[quad_index];
|
||||||
|
*(target_16++) = source_16[quad_index + 1];
|
||||||
|
*(target_16++) = source_16[quad_index + 2];
|
||||||
|
*(target_16++) = source_16[quad_index];
|
||||||
|
*(target_16++) = source_16[quad_index + 2];
|
||||||
|
*(target_16++) = source_16[quad_index + 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache and return the indices.
|
// Cache and return the indices.
|
||||||
|
@ -662,7 +721,7 @@ void PrimitiveConverter::MemoryWriteCallbackThunk(void* context_ptr,
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS PrimitiveConverter::GetStaticIndexBuffer(
|
D3D12_GPU_VIRTUAL_ADDRESS PrimitiveConverter::GetStaticIndexBuffer(
|
||||||
PrimitiveType source_type, uint32_t index_count,
|
PrimitiveType source_type, uint32_t index_count,
|
||||||
uint32_t& index_count_out) const {
|
uint32_t& index_count_out) const {
|
||||||
if (index_count >= kMaxNonIndexedVertices) {
|
if (index_count > kMaxNonIndexedVertices) {
|
||||||
assert_always();
|
assert_always();
|
||||||
return D3D12_GPU_VIRTUAL_ADDRESS(0);
|
return D3D12_GPU_VIRTUAL_ADDRESS(0);
|
||||||
}
|
}
|
||||||
|
@ -671,6 +730,11 @@ D3D12_GPU_VIRTUAL_ADDRESS PrimitiveConverter::GetStaticIndexBuffer(
|
||||||
return static_ib_gpu_address_ +
|
return static_ib_gpu_address_ +
|
||||||
kStaticIBTriangleFanOffset * sizeof(uint16_t);
|
kStaticIBTriangleFanOffset * sizeof(uint16_t);
|
||||||
}
|
}
|
||||||
|
if (source_type == PrimitiveType::kQuadList &&
|
||||||
|
FLAGS_d3d12_convert_quads_to_triangles) {
|
||||||
|
index_count_out = (index_count >> 2) * 6;
|
||||||
|
return static_ib_gpu_address_ + kStaticIBQuadOffset * sizeof(uint16_t);
|
||||||
|
}
|
||||||
return D3D12_GPU_VIRTUAL_ADDRESS(0);
|
return D3D12_GPU_VIRTUAL_ADDRESS(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ class D3D12CommandProcessor;
|
||||||
// - Line loops (only indexed ones - non-indexed are better handled in vertex
|
// - Line loops (only indexed ones - non-indexed are better handled in vertex
|
||||||
// shaders, otherwise a whole index buffer would have to be created for every
|
// shaders, otherwise a whole index buffer would have to be created for every
|
||||||
// vertex count value).
|
// vertex count value).
|
||||||
|
// - Quad lists (for debugging since geometry shaders break PIX - as an
|
||||||
|
// alternative to the geometry shader).
|
||||||
class PrimitiveConverter {
|
class PrimitiveConverter {
|
||||||
public:
|
public:
|
||||||
PrimitiveConverter(D3D12CommandProcessor* command_processor,
|
PrimitiveConverter(D3D12CommandProcessor* command_processor,
|
||||||
|
@ -111,8 +113,12 @@ class PrimitiveConverter {
|
||||||
static constexpr uint32_t kStaticIBTriangleFanOffset = 0;
|
static constexpr uint32_t kStaticIBTriangleFanOffset = 0;
|
||||||
static constexpr uint32_t kStaticIBTriangleFanCount =
|
static constexpr uint32_t kStaticIBTriangleFanCount =
|
||||||
(kMaxNonIndexedVertices - 2) * 3;
|
(kMaxNonIndexedVertices - 2) * 3;
|
||||||
static constexpr uint32_t kStaticIBTotalCount =
|
static constexpr uint32_t kStaticIBQuadOffset =
|
||||||
kStaticIBTriangleFanOffset + kStaticIBTriangleFanCount;
|
kStaticIBTriangleFanOffset + kStaticIBTriangleFanCount;
|
||||||
|
static constexpr uint32_t kStaticIBQuadCount =
|
||||||
|
(kMaxNonIndexedVertices >> 2) * 6;
|
||||||
|
static constexpr uint32_t kStaticIBTotalCount =
|
||||||
|
kStaticIBQuadOffset + kStaticIBQuadCount;
|
||||||
|
|
||||||
// Not identifying the index buffer uniquely - reset index must also be
|
// Not identifying the index buffer uniquely - reset index must also be
|
||||||
// checked if reset is enabled.
|
// checked if reset is enabled.
|
||||||
|
@ -123,7 +129,7 @@ class PrimitiveConverter {
|
||||||
PrimitiveType source_type : 6; // 38
|
PrimitiveType source_type : 6; // 38
|
||||||
IndexFormat format : 1; // 39
|
IndexFormat format : 1; // 39
|
||||||
uint32_t count : 16; // 55
|
uint32_t count : 16; // 55
|
||||||
uint32_t reset : 1; // 56;
|
uint32_t reset : 1; // 56
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clearing the unused bits.
|
// Clearing the unused bits.
|
||||||
|
|
Loading…
Reference in New Issue