[D3D12] Compact float constants and don't split them into pages

This commit is contained in:
Triang3l
2018-09-30 20:17:26 +03:00
parent eb50ebd885
commit c4599ff211
7 changed files with 733 additions and 485 deletions

View File

@@ -26,6 +26,17 @@ class DxbcShaderTranslator : public ShaderTranslator {
DxbcShaderTranslator();
~DxbcShaderTranslator() override;
// Constant buffer bindings in space 0.
enum class CbufferRegister {
// The D3D12 command processor has system and bool/loop constants in a
// single descriptor range.
// TODO(Triang3l): Make them root CBVs for speed.
kSystemConstants,
kBoolLoopConstants,
kFloatConstants,
kFetchConstants,
};
enum : uint32_t {
kSysFlag_XYDividedByW = 1,
kSysFlag_ZDividedByW = kSysFlag_XYDividedByW << 1,
@@ -38,9 +49,8 @@ class DxbcShaderTranslator : public ShaderTranslator {
};
// IF SYSTEM CONSTANTS ARE CHANGED OR ADDED, THE FOLLOWING MUST BE UPDATED:
// - kSysConst enum (registers and first components).
// - rdef_constants_.
// - rdef_constant_buffers_ system constant buffer size.
// - kSysConst enum (indices, registers and first components).
// - system_constant_rdef_.
// - d3d12/shaders/xenos_draw.hlsli (for geometry shaders).
struct SystemConstants {
// vec4 0
@@ -144,54 +154,59 @@ class DxbcShaderTranslator : public ShaderTranslator {
void ProcessAluInstruction(const ParsedAluInstruction& instr) override;
private:
static constexpr uint32_t kFloatConstantsPerPage = 32;
static constexpr uint32_t kFloatConstantPageCount = 8;
// Constant buffer bindings in space 0.
enum class CbufferRegister {
kSystemConstants,
kBoolLoopConstants,
kFetchConstants,
kFloatConstantsFirst,
kFloatConstantsLast = kFloatConstantsFirst + kFloatConstantPageCount - 1,
};
enum : uint32_t {
kSysConst_Flags_Index = 0,
kSysConst_Flags_Vec = 0,
kSysConst_Flags_Comp = 0,
kSysConst_VertexIndexEndian_Index = kSysConst_Flags_Index + 1,
kSysConst_VertexIndexEndian_Vec = 0,
kSysConst_VertexIndexEndian_Comp = 1,
kSysConst_VertexBaseIndex_Index = kSysConst_VertexIndexEndian_Index + 1,
kSysConst_VertexBaseIndex_Vec = 0,
kSysConst_VertexBaseIndex_Comp = 2,
kSysConst_PixelPosReg_Index = kSysConst_VertexBaseIndex_Index + 1,
kSysConst_PixelPosReg_Vec = 0,
kSysConst_PixelPosReg_Comp = 3,
kSysConst_NDCScale_Index = kSysConst_PixelPosReg_Index + 1,
kSysConst_NDCScale_Vec = 1,
kSysConst_NDCScale_Comp = 0,
kSysConst_PixelHalfPixelOffset_Index = kSysConst_NDCScale_Index + 1,
kSysConst_PixelHalfPixelOffset_Vec = 1,
kSysConst_PixelHalfPixelOffset_Comp = 3,
kSysConst_NDCOffset_Index = kSysConst_PixelHalfPixelOffset_Index + 1,
kSysConst_NDCOffset_Vec = 2,
kSysConst_NDCOffset_Comp = 0,
kSysConst_AlphaTest_Index = kSysConst_NDCOffset_Index + 1,
kSysConst_AlphaTest_Vec = 2,
kSysConst_AlphaTest_Comp = 3,
kSysConst_PointSize_Index = kSysConst_AlphaTest_Index + 1,
kSysConst_PointSize_Vec = 3,
kSysConst_PointSize_Comp = 0,
kSysConst_PointSizeMinMax_Index = kSysConst_PointSize_Index + 1,
kSysConst_PointSizeMinMax_Vec = 3,
kSysConst_PointSizeMinMax_Comp = 2,
kSysConst_PointScreenToNDC_Index = kSysConst_PointSizeMinMax_Index + 1,
kSysConst_PointScreenToNDC_Vec = 4,
kSysConst_PointScreenToNDC_Comp = 0,
kSysConst_SSAAInvScale_Index = kSysConst_PointScreenToNDC_Index + 1,
kSysConst_SSAAInvScale_Vec = 4,
kSysConst_SSAAInvScale_Comp = 2,
kSysConst_AlphaTestRange_Index = kSysConst_SSAAInvScale_Index + 1,
kSysConst_AlphaTestRange_Vec = 5,
kSysConst_AlphaTestRange_Comp = 0,
kSysConst_ColorExpBias_Index = kSysConst_AlphaTestRange_Index + 1,
kSysConst_ColorExpBias_Vec = 6,
kSysConst_ColorOutputMap_Index = kSysConst_ColorExpBias_Index + 1,
kSysConst_ColorOutputMap_Vec = 7,
kSysConst_Count = kSysConst_ColorOutputMap_Index + 1
};
static constexpr uint32_t kInterpolatorCount = 16;
@@ -316,7 +331,9 @@ class DxbcShaderTranslator : public ShaderTranslator {
Type type;
uint32_t index;
bool is_dynamic_indexed;
// If the operand is dynamically indexed directly when it's used as an
// operand in DXBC instructions.
InstructionStorageAddressingMode addressing_mode;
uint32_t swizzle;
bool is_negated;
@@ -421,15 +438,14 @@ class DxbcShaderTranslator : public ShaderTranslator {
kInt,
kUint,
kUint4,
// Float constants - size written dynamically.
kFloat4ConstantArray,
// Bool constants.
kUint4Array8,
// Loop constants.
kUint4Array32,
// Fetch constants.
kUint4Array48,
// Float constants in one page.
kFloatConstantPageArray,
kFloatConstantPageStruct,
kCount,
kUnknown = kCount
@@ -440,7 +456,6 @@ class DxbcShaderTranslator : public ShaderTranslator {
RdefTypeIndex type;
uint32_t offset;
};
static const RdefStructMember rdef_float_constant_page_member_;
struct RdefType {
// Name ignored for arrays.
@@ -459,73 +474,35 @@ class DxbcShaderTranslator : public ShaderTranslator {
};
static const RdefType rdef_types_[size_t(RdefTypeIndex::kCount)];
enum class RdefConstantIndex {
kSystemConstantFirst,
kSysFlags = kSystemConstantFirst,
kSysVertexBaseIndex,
kSysVertexIndexEndian,
kSysPixelPosReg,
kSysNDCScale,
kSysPixelHalfPixelOffset,
kSysNDCOffset,
kSysAlphaTest,
kSysPointSize,
kSysPointSizeMinMax,
kSysPointScreenToNDC,
kSysSSAAInvScale,
kSysAlphaTestRange,
kSysColorExpBias,
kSysColorOutputMap,
kSystemConstantLast = kSysColorOutputMap,
// Number of constant buffer bindings used in this shader - also used for
// generation of indices of constant buffers that are optional.
uint32_t cbuffer_count_;
static constexpr uint32_t kCbufferIndexUnallocated = UINT32_MAX;
uint32_t cbuffer_index_system_constants_;
uint32_t cbuffer_index_float_constants_;
uint32_t cbuffer_index_bool_loop_constants_;
uint32_t cbuffer_index_fetch_constants_;
kBoolConstants,
kLoopConstants,
kFetchConstants,
kFloatConstants,
kCount,
kSystemConstantCount = kSystemConstantLast - kSystemConstantFirst + 1,
};
struct RdefConstant {
struct SystemConstantRdef {
const char* name;
RdefTypeIndex type;
uint32_t offset;
uint32_t size;
};
static const RdefConstant rdef_constants_[size_t(RdefConstantIndex::kCount)];
static_assert(uint32_t(RdefConstantIndex::kCount) <= 64,
"Too many constants in all constant buffers - can't use a 64 "
"bit vector to store which constants are used");
uint64_t rdef_constants_used_;
static const SystemConstantRdef system_constant_rdef_[kSysConst_Count];
// Mask of system constants (1 << kSysConst_#_Index) used in the shader, so
// the remaining ones can be marked as unused in RDEF.
uint32_t system_constants_used_;
enum class RdefConstantBufferIndex {
kSystemConstants,
kBoolLoopConstants,
kFetchConstants,
kFloatConstants,
// Whether constants are dynamically indexed and need to be marked as such in
// dcl_constantBuffer.
bool float_constants_dynamic_indexed_;
bool bool_loop_constants_dynamic_indexed_;
kCount
};
struct RdefConstantBuffer {
const char* name;
RdefConstantIndex first_constant;
uint32_t constant_count;
uint32_t size;
CbufferRegister register_index;
uint32_t binding_count;
// True if created like `cbuffer`, false for `ConstantBuffer<T>`.
bool user_packed;
bool dynamic_indexed;
};
static const RdefConstantBuffer
rdef_constant_buffers_[size_t(RdefConstantBufferIndex::kCount)];
// Order of dcl_constantbuffer instructions, from most frequenly accessed to
// least frequently accessed (hint to driver according to the DXBC header).
static const RdefConstantBufferIndex
constant_buffer_dcl_order_[size_t(RdefConstantBufferIndex::kCount)];
// Offsets of float constant indices in shader_code_, for remapping in
// CompleteTranslation (initially, at these offsets, guest float constant
// indices are written).
std::vector<uint32_t> float_constant_index_offsets_;
// Number of currently allocated Xenia internal r# registers.
uint32_t system_temp_count_current_;