[D3D12] Rewrite pipeline cache for compact storage of pipeline descriptions
This commit is contained in:
parent
317e5c3ce2
commit
1cea4062c0
|
@ -1310,11 +1310,10 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||||
// Create the pipeline if needed and bind it.
|
// Create the pipeline if needed and bind it.
|
||||||
ID3D12PipelineState* pipeline;
|
ID3D12PipelineState* pipeline;
|
||||||
ID3D12RootSignature* root_signature;
|
ID3D12RootSignature* root_signature;
|
||||||
auto pipeline_status = pipeline_cache_->ConfigurePipeline(
|
if (!pipeline_cache_->ConfigurePipeline(
|
||||||
vertex_shader, pixel_shader, primitive_type_converted,
|
vertex_shader, pixel_shader, primitive_type_converted,
|
||||||
indexed ? index_buffer_info->format : IndexFormat::kInt16,
|
indexed ? index_buffer_info->format : IndexFormat::kInt16,
|
||||||
pipeline_render_targets, &pipeline, &root_signature);
|
pipeline_render_targets, &pipeline, &root_signature)) {
|
||||||
if (pipeline_status == PipelineCache::UpdateStatus::kError) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (current_pipeline_ != pipeline) {
|
if (current_pipeline_ != pipeline) {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -13,8 +13,6 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "third_party/xxhash/xxhash.h"
|
|
||||||
|
|
||||||
#include "xenia/gpu/d3d12/d3d12_shader.h"
|
#include "xenia/gpu/d3d12/d3d12_shader.h"
|
||||||
#include "xenia/gpu/d3d12/render_target_cache.h"
|
#include "xenia/gpu/d3d12/render_target_cache.h"
|
||||||
#include "xenia/gpu/dxbc_shader_translator.h"
|
#include "xenia/gpu/dxbc_shader_translator.h"
|
||||||
|
@ -29,12 +27,6 @@ class D3D12CommandProcessor;
|
||||||
|
|
||||||
class PipelineCache {
|
class PipelineCache {
|
||||||
public:
|
public:
|
||||||
enum class UpdateStatus {
|
|
||||||
kCompatible,
|
|
||||||
kMismatch,
|
|
||||||
kError,
|
|
||||||
};
|
|
||||||
|
|
||||||
PipelineCache(D3D12CommandProcessor* command_processor,
|
PipelineCache(D3D12CommandProcessor* command_processor,
|
||||||
RegisterFile* register_file, bool edram_rov_used);
|
RegisterFile* register_file, bool edram_rov_used);
|
||||||
~PipelineCache();
|
~PipelineCache();
|
||||||
|
@ -49,7 +41,7 @@ class PipelineCache {
|
||||||
D3D12Shader* pixel_shader,
|
D3D12Shader* pixel_shader,
|
||||||
PrimitiveType primitive_type);
|
PrimitiveType primitive_type);
|
||||||
|
|
||||||
UpdateStatus ConfigurePipeline(
|
bool ConfigurePipeline(
|
||||||
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader,
|
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader,
|
||||||
PrimitiveType primitive_type, IndexFormat index_format,
|
PrimitiveType primitive_type, IndexFormat index_format,
|
||||||
const RenderTargetCache::PipelineRenderTarget render_targets[5],
|
const RenderTargetCache::PipelineRenderTarget render_targets[5],
|
||||||
|
@ -59,31 +51,122 @@ class PipelineCache {
|
||||||
void ClearCache();
|
void ClearCache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool SetShadowRegister(uint32_t* dest, uint32_t register_name);
|
enum class PipelineStripCutIndex : uint32_t {
|
||||||
bool SetShadowRegister(float* dest, uint32_t register_name);
|
kNone,
|
||||||
|
kFFFF,
|
||||||
|
kFFFFFFFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PipelineTessellationMode : uint32_t {
|
||||||
|
kNone,
|
||||||
|
kDiscrete,
|
||||||
|
kContinuous,
|
||||||
|
kAdaptive,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PipelinePatchType : uint32_t {
|
||||||
|
kNone,
|
||||||
|
kLine,
|
||||||
|
kTriangle,
|
||||||
|
kQuad,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PipelinePrimitiveTopologyType : uint32_t {
|
||||||
|
kPoint,
|
||||||
|
kLine,
|
||||||
|
kTriangle,
|
||||||
|
kPatch,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PipelineGeometryShader : uint32_t {
|
||||||
|
kNone,
|
||||||
|
kPointList,
|
||||||
|
kRectangleList,
|
||||||
|
kQuadList,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PipelineCullMode : uint32_t {
|
||||||
|
kNone,
|
||||||
|
kFront,
|
||||||
|
kBack,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class PipelineBlendFactor : uint32_t {
|
||||||
|
kZero,
|
||||||
|
kOne,
|
||||||
|
kSrcColor,
|
||||||
|
kInvSrcColor,
|
||||||
|
kSrcAlpha,
|
||||||
|
kInvSrcAlpha,
|
||||||
|
kDestColor,
|
||||||
|
kInvDestColor,
|
||||||
|
kDestAlpha,
|
||||||
|
kInvDestAlpha,
|
||||||
|
kBlendFactor,
|
||||||
|
kInvBlendFactor,
|
||||||
|
kSrcAlphaSat,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PipelineRenderTarget {
|
||||||
|
uint32_t used : 1; // 1
|
||||||
|
ColorRenderTargetFormat format : 4; // 5
|
||||||
|
PipelineBlendFactor src_blend : 4; // 9
|
||||||
|
PipelineBlendFactor dest_blend : 4; // 13
|
||||||
|
BlendOp blend_op : 3; // 16
|
||||||
|
PipelineBlendFactor src_blend_alpha : 4; // 20
|
||||||
|
PipelineBlendFactor dest_blend_alpha : 4; // 24
|
||||||
|
BlendOp blend_op_alpha : 3; // 27
|
||||||
|
uint32_t write_mask : 4; // 31
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PipelineDescription {
|
||||||
|
ID3D12RootSignature* root_signature;
|
||||||
|
D3D12Shader* vertex_shader;
|
||||||
|
D3D12Shader* pixel_shader;
|
||||||
|
|
||||||
|
int32_t depth_bias;
|
||||||
|
float depth_bias_slope_scaled;
|
||||||
|
|
||||||
|
PipelineStripCutIndex strip_cut_index : 2; // 2
|
||||||
|
PipelineTessellationMode tessellation_mode : 2; // 4
|
||||||
|
PipelinePrimitiveTopologyType primitive_topology_type : 2; // 6
|
||||||
|
PipelinePatchType patch_type : 2; // 8
|
||||||
|
PipelineGeometryShader geometry_shader : 2; // 10
|
||||||
|
uint32_t fill_mode_wireframe : 1; // 11
|
||||||
|
PipelineCullMode cull_mode : 2; // 13
|
||||||
|
uint32_t front_counter_clockwise : 1; // 14
|
||||||
|
uint32_t depth_clip : 1; // 15
|
||||||
|
uint32_t rov_msaa : 1; // 16
|
||||||
|
DepthRenderTargetFormat depth_format : 1; // 17
|
||||||
|
uint32_t depth_func : 3; // 20
|
||||||
|
uint32_t depth_write : 1; // 21
|
||||||
|
uint32_t stencil_enable : 1; // 22
|
||||||
|
uint32_t stencil_read_mask : 8; // 30
|
||||||
|
|
||||||
|
uint32_t stencil_write_mask : 8; // 8
|
||||||
|
uint32_t stencil_front_fail_op : 3; // 11
|
||||||
|
uint32_t stencil_front_depth_fail_op : 3; // 14
|
||||||
|
uint32_t stencil_front_pass_op : 3; // 17
|
||||||
|
uint32_t stencil_front_func : 3; // 20
|
||||||
|
uint32_t stencil_back_fail_op : 3; // 23
|
||||||
|
uint32_t stencil_back_depth_fail_op : 3; // 26
|
||||||
|
uint32_t stencil_back_pass_op : 3; // 29
|
||||||
|
uint32_t stencil_back_func : 3; // 32
|
||||||
|
|
||||||
|
PipelineRenderTarget render_targets[4];
|
||||||
|
};
|
||||||
|
|
||||||
bool TranslateShader(D3D12Shader* shader, xenos::xe_gpu_program_cntl_t cntl,
|
bool TranslateShader(D3D12Shader* shader, xenos::xe_gpu_program_cntl_t cntl,
|
||||||
PrimitiveType primitive_type);
|
PrimitiveType primitive_type);
|
||||||
|
|
||||||
UpdateStatus UpdateState(
|
bool GetCurrentStateDescription(
|
||||||
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader,
|
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader,
|
||||||
PrimitiveType primitive_type, IndexFormat index_format,
|
PrimitiveType primitive_type, IndexFormat index_format,
|
||||||
const RenderTargetCache::PipelineRenderTarget render_targets[5]);
|
const RenderTargetCache::PipelineRenderTarget render_targets[5],
|
||||||
|
PipelineDescription& description_out);
|
||||||
|
|
||||||
// pRootSignature, VS, PS, DS, HS, GS, PrimitiveTopologyType.
|
ID3D12PipelineState* CreatePipelineState(
|
||||||
UpdateStatus UpdateShaderStages(D3D12Shader* vertex_shader,
|
const PipelineDescription& description);
|
||||||
D3D12Shader* pixel_shader,
|
|
||||||
PrimitiveType primitive_type);
|
|
||||||
// BlendState, NumRenderTargets, RTVFormats.
|
|
||||||
UpdateStatus UpdateBlendStateAndRenderTargets(
|
|
||||||
D3D12Shader* pixel_shader,
|
|
||||||
const RenderTargetCache::PipelineRenderTarget render_targets[4]);
|
|
||||||
// RasterizerState.
|
|
||||||
UpdateStatus UpdateRasterizerState(PrimitiveType primitive_type);
|
|
||||||
// DepthStencilState, DSVFormat.
|
|
||||||
UpdateStatus UpdateDepthStencilState(DXGI_FORMAT format);
|
|
||||||
// IBStripCutValue.
|
|
||||||
UpdateStatus UpdateIBStripCutValue(IndexFormat index_format);
|
|
||||||
|
|
||||||
D3D12CommandProcessor* command_processor_;
|
D3D12CommandProcessor* command_processor_;
|
||||||
RegisterFile* register_file_;
|
RegisterFile* register_file_;
|
||||||
|
@ -100,85 +183,17 @@ class PipelineCache {
|
||||||
// Xenos pixel shader provided.
|
// Xenos pixel shader provided.
|
||||||
std::vector<uint8_t> depth_only_pixel_shader_;
|
std::vector<uint8_t> depth_only_pixel_shader_;
|
||||||
|
|
||||||
// Hash state used to incrementally produce pipeline hashes during update.
|
|
||||||
// By the time the full update pass has run the hash will represent the
|
|
||||||
// current state in a way that can uniquely identify the produced
|
|
||||||
// ID3D12PipelineState.
|
|
||||||
XXH64_state_t hash_state_;
|
|
||||||
struct Pipeline {
|
struct Pipeline {
|
||||||
ID3D12PipelineState* state;
|
ID3D12PipelineState* state;
|
||||||
// Root signature taken from the command processor.
|
PipelineDescription description;
|
||||||
ID3D12RootSignature* root_signature;
|
|
||||||
};
|
};
|
||||||
// All previously generated pipelines mapped by hash.
|
// All previously generated pipelines mapped by hash.
|
||||||
std::unordered_map<uint64_t, Pipeline*> pipelines_;
|
std::unordered_map<uint64_t, Pipeline*> pipelines_;
|
||||||
Pipeline* GetPipeline(uint64_t hash_key);
|
|
||||||
|
|
||||||
// Previously used pipeline. This matches our current state settings
|
// Previously used pipeline. This matches our current state settings
|
||||||
// and allows us to quickly(ish) reuse the pipeline if no registers have
|
// and allows us to quickly(ish) reuse the pipeline if no registers have
|
||||||
// changed.
|
// changed.
|
||||||
Pipeline* current_pipeline_ = nullptr;
|
Pipeline* current_pipeline_ = nullptr;
|
||||||
|
|
||||||
// Description of the pipeline being created.
|
|
||||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC update_desc_;
|
|
||||||
|
|
||||||
struct UpdateShaderStagesRegisters {
|
|
||||||
D3D12Shader* vertex_shader;
|
|
||||||
D3D12Shader* pixel_shader;
|
|
||||||
D3D12_PRIMITIVE_TOPOLOGY_TYPE primitive_topology_type;
|
|
||||||
// Primitive type if it needs hull/domain shaders or a geometry shader, or
|
|
||||||
// kNone if should be transformed with only a vertex shader.
|
|
||||||
PrimitiveType hs_gs_ds_primitive_type;
|
|
||||||
// Tessellation mode - ignored when not using tessellation (when
|
|
||||||
// hs_gs_ds_primitive_type is not a patch).
|
|
||||||
TessellationMode tessellation_mode;
|
|
||||||
|
|
||||||
UpdateShaderStagesRegisters() { Reset(); }
|
|
||||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
|
||||||
} update_shader_stages_regs_;
|
|
||||||
|
|
||||||
struct UpdateBlendStateAndRenderTargetsRegisters {
|
|
||||||
RenderTargetCache::PipelineRenderTarget render_targets[5];
|
|
||||||
// RB_COLOR_MASK with unused render targets removed.
|
|
||||||
uint32_t color_mask;
|
|
||||||
// Blend control updated only for used render targets.
|
|
||||||
uint32_t blendcontrol[4];
|
|
||||||
bool colorcontrol_blend_enable;
|
|
||||||
|
|
||||||
UpdateBlendStateAndRenderTargetsRegisters() { Reset(); }
|
|
||||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
|
||||||
} update_blend_state_and_render_targets_regs_;
|
|
||||||
|
|
||||||
struct UpdateRasterizerStateRegisters {
|
|
||||||
// The constant factor of the polygon offset is multiplied by a value that
|
|
||||||
// depends on the depth buffer format here.
|
|
||||||
float poly_offset;
|
|
||||||
float poly_offset_scale;
|
|
||||||
uint8_t cull_mode;
|
|
||||||
bool fill_mode_wireframe;
|
|
||||||
bool front_counter_clockwise;
|
|
||||||
bool depth_clamp_enable;
|
|
||||||
bool msaa_rov;
|
|
||||||
|
|
||||||
UpdateRasterizerStateRegisters() { Reset(); }
|
|
||||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
|
||||||
} update_rasterizer_state_regs_;
|
|
||||||
|
|
||||||
struct UpdateDepthStencilStateRegisters {
|
|
||||||
DXGI_FORMAT format;
|
|
||||||
uint32_t rb_depthcontrol;
|
|
||||||
uint32_t rb_stencilrefmask;
|
|
||||||
|
|
||||||
UpdateDepthStencilStateRegisters() { Reset(); }
|
|
||||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
|
||||||
} update_depth_stencil_state_regs_;
|
|
||||||
|
|
||||||
struct UpdateIBStripCutValueRegisters {
|
|
||||||
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE ib_strip_cut_value;
|
|
||||||
|
|
||||||
UpdateIBStripCutValueRegisters() { Reset(); }
|
|
||||||
void Reset() { std::memset(this, 0, sizeof(*this)); }
|
|
||||||
} update_ib_strip_cut_value_regs_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace d3d12
|
} // namespace d3d12
|
||||||
|
|
Loading…
Reference in New Issue