From 6d783fd3bf3402df5901978329bddb39599b962e Mon Sep 17 00:00:00 2001 From: Triang3l Date: Wed, 29 Aug 2018 16:57:29 +0300 Subject: [PATCH] [D3D12] DXBC RDEF types --- src/xenia/gpu/dxbc_shader_translator.cc | 111 ++++++++++++++++--- src/xenia/gpu/dxbc_shader_translator.h | 137 ++++++++++++++++++++++++ 2 files changed, 236 insertions(+), 12 deletions(-) diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index 2b1b0c9c3..dc2f26893 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -28,6 +28,8 @@ void DxbcShaderTranslator::Reset() { ShaderTranslator::Reset(); shader_code_.clear(); + + rdef_constants_used_ = 0; } std::vector DxbcShaderTranslator::CompleteTranslation() { @@ -89,20 +91,43 @@ uint32_t DxbcShaderTranslator::AppendString(std::vector& dest, return uint32_t(size_aligned); } +const DxbcShaderTranslator::RdefStructMember + DxbcShaderTranslator::rdef_float_constant_page_member_ = { + "c", RdefTypeIndex::kFloat4Array32, 0}; + +const DxbcShaderTranslator::RdefType DxbcShaderTranslator::rdef_types_[size_t( + DxbcShaderTranslator::RdefTypeIndex::kCount)] = { + {"float", 0, 3, 1, 1, 0, 0, RdefTypeIndex::kUnknown, nullptr}, + {"float2", 1, 3, 1, 2, 0, 0, RdefTypeIndex::kUnknown, nullptr}, + {"float3", 1, 3, 1, 3, 0, 0, RdefTypeIndex::kUnknown, nullptr}, + {"float4", 1, 3, 1, 4, 0, 0, RdefTypeIndex::kUnknown, nullptr}, + {"int", 0, 2, 1, 1, 0, 0, RdefTypeIndex::kUnknown, nullptr}, + {"uint", 0, 19, 1, 1, 0, 0, RdefTypeIndex::kUnknown, nullptr}, + {"uint4", 1, 19, 1, 4, 0, 0, RdefTypeIndex::kUnknown, nullptr}, + {nullptr, 1, 3, 1, 4, 20, 0, RdefTypeIndex::kFloat4, nullptr}, + {nullptr, 1, 19, 1, 4, 8, 0, RdefTypeIndex::kUint4, nullptr}, + {nullptr, 1, 19, 1, 4, 32, 0, RdefTypeIndex::kUint4, nullptr}, + {nullptr, 1, 19, 1, 4, 48, 0, RdefTypeIndex::kUint4, nullptr}, + {"XeFloatConstantPage", 5, 0, 1, 128, 1, 1, RdefTypeIndex::kUnknown, + &rdef_float_constant_page_member_}, +}; + void DxbcShaderTranslator::WriteResourceDefinitions() { uint32_t chunk_position_dwords = uint32_t(shader_object_.size()); + uint32_t new_offset; - // Write the header. + // TODO(Triang3l): Include shared memory, textures, samplers. + uint32_t binding_count = uint32_t(RdefConstantBufferIndex::kCount); + + // *************************************************************************** + // Header + // *************************************************************************** // Constant buffer count. - // b0 - Xenia system constants. - // b1 - bool and loop constants. - // b2 - fetch constants. - // b3-b10 - float constants. - shader_object_.push_back(4); + shader_object_.push_back(uint32_t(RdefConstantBufferIndex::kCount)); // Constant buffer offset (set later). shader_object_.push_back(0); - // TODO(Triang3l): Bound resource count (CBV + other views) (set later). - shader_object_.push_back(4); + // Bound resource count (CBV, SRV, UAV, samplers). + shader_object_.push_back(binding_count); // TODO(Triang3l): Bound resource buffer offset (set later). shader_object_.push_back(0); if (is_vertex_shader()) { @@ -131,10 +156,72 @@ void DxbcShaderTranslator::WriteResourceDefinitions() { // Generator name. AppendString(shader_object_, "Xenia"); - // Constant buffers. - uint32_t cbuffer_position_dwords = uint32_t(shader_object_.size()); - shader_object_[chunk_position_dwords + 1] = - cbuffer_position_dwords * sizeof(uint32_t); + // *************************************************************************** + // Constant types + // *************************************************************************** + // Type names. + new_offset = (uint32_t(shader_object_.size()) - chunk_position_dwords) * + sizeof(uint32_t); + uint32_t type_name_offsets[size_t(RdefTypeIndex::kCount)]; + for (uint32_t i = 0; i < uint32_t(RdefTypeIndex::kCount); ++i) { + const RdefType& type = rdef_types_[i]; + if (type.name == nullptr) { + // Array - use the name of the element type. + type_name_offsets[i] = + type_name_offsets[uint32_t(type.array_element_type)]; + continue; + } + type_name_offsets[i] = new_offset; + new_offset += AppendString(shader_object_, type.name); + } + // Types. + uint32_t types_position_dwords = uint32_t(shader_object_.size()); + const uint32_t type_size_dwords = 9; + uint32_t types_offset = + (types_position_dwords - chunk_position_dwords) * sizeof(uint32_t); + const uint32_t type_size = type_size_dwords * sizeof(uint32_t); + for (uint32_t i = 0; i < uint32_t(RdefTypeIndex::kCount); ++i) { + const RdefType& type = rdef_types_[i]; + shader_object_.push_back(type.type_class | (type.type << 16)); + shader_object_.push_back(type.row_count | (type.column_count << 16)); + shader_object_.push_back(type.element_count | + (type.struct_member_count << 16)); + // Struct member offset (set later). + shader_object_.push_back(0); + // Unknown. + shader_object_.push_back(0); + shader_object_.push_back(0); + shader_object_.push_back(0); + shader_object_.push_back(0); + shader_object_.push_back(type_name_offsets[i]); + } + // Struct members. + for (uint32_t i = 0; i < uint32_t(RdefTypeIndex::kCount); ++i) { + const RdefType& type = rdef_types_[i]; + const RdefStructMember* struct_members = type.struct_members; + if (struct_members == nullptr) { + continue; + } + uint32_t struct_member_position_dwords = uint32_t(shader_object_.size()); + shader_object_[types_position_dwords + i * type_size_dwords + 3] = + (struct_member_position_dwords - chunk_position_dwords) * + sizeof(uint32_t); + uint32_t struct_member_count = type.struct_member_count; + // Reserve space for names and write types and offsets. + for (uint32_t j = 0; j < struct_member_count; ++j) { + shader_object_.push_back(0); + shader_object_.push_back(types_offset + + uint32_t(struct_members[j].type) * type_size); + shader_object_.push_back(struct_members[j].offset); + } + // Write member names. + new_offset = (uint32_t(shader_object_.size()) - chunk_position_dwords) * + sizeof(uint32_t); + for (uint32_t j = 0; j < struct_member_count; ++j) { + shader_object_[struct_member_position_dwords + j * 3] = new_offset; + new_offset += AppendString(shader_object_, struct_members[j].name); + } + } } } // namespace gpu diff --git a/src/xenia/gpu/dxbc_shader_translator.h b/src/xenia/gpu/dxbc_shader_translator.h index 509f7145e..04541954a 100644 --- a/src/xenia/gpu/dxbc_shader_translator.h +++ b/src/xenia/gpu/dxbc_shader_translator.h @@ -23,6 +23,37 @@ class DxbcShaderTranslator : public ShaderTranslator { DxbcShaderTranslator(); ~DxbcShaderTranslator() override; + struct SystemConstants { + // vec4 0 + float mul_rcp_w[3]; + uint32_t vertex_base_index; + + // vec4 1 + float ndc_scale[3]; + uint32_t vertex_index_endian; + + // vec4 2 + float ndc_offset[3]; + float pixel_half_pixel_offset; + + // vec4 3 + float point_size[2]; + float ssaa_inv_scale[2]; + + // vec3 4 + uint32_t pixel_pos_reg; + // 0 - disabled, 1 - passes if in range, -1 - fails if in range. + int32_t alpha_test; + // The range is floats as uints so it's easier to pass infinity. + uint32_t alpha_test_range[2]; + + // vec4 5 + float color_exp_bias[4]; + + // vec4 6 + uint32_t color_output_map[4]; + }; + protected: void Reset() override; @@ -39,6 +70,112 @@ class DxbcShaderTranslator : public ShaderTranslator { // Complete shader object, with all the needed chunks and dcl_ instructions - // generated in the end of translation. std::vector shader_object_; + + // Data types used in constants buffers. Listed in dependency order. + enum class RdefTypeIndex { + kFloat, + kFloat2, + kFloat3, + kFloat4, + kInt, + kUint, + kUint4, + // Float constants in one page. + kFloat4Array32, + // Bool constants. + kUint4Array8, + // Loop constants. + kUint4Array32, + // Fetch constants. + kUint4Array48, + kFloatConstantPageStruct, + + kCount, + kUnknown = kCount + }; + + struct RdefStructMember { + const char* name; + RdefTypeIndex type; + uint32_t offset; + }; + static const RdefStructMember rdef_float_constant_page_member_; + + struct RdefType { + // Name ignored for arrays. + const char* name; + // D3D10_SHADER_VARIABLE_CLASS. + uint32_t type_class; + // D3D10_SHADER_VARIABLE_TYPE. + uint32_t type; + uint32_t row_count; + uint32_t column_count; + // 0 for primitive types, 1 for structures, array size for arrays. + uint32_t element_count; + uint32_t struct_member_count; + RdefTypeIndex array_element_type; + const RdefStructMember* struct_members; + }; + static const RdefType rdef_types_[size_t(RdefTypeIndex::kCount)]; + + enum class RdefConstantIndex { + kSystemConstantFirst, + kSysMulRcpW = kSystemConstantFirst, + kSysVertexBaseIndex, + kSysNDCScale, + kSysVertexIndexEndian, + kSysNDCOffset, + kSysPixelHalfPixelOffset, + kSysPointSize, + kSysSSAAInvScale, + kSysPixelPosReg, + kSysAlphaTest, + kSysAlphaTestRange, + kSysColorExpBias, + kSysColorOutputMap, + kSystemConstantLast = kSysColorOutputMap, + + kBoolConstants, + kLoopConstants, + + kFetchConstants, + + kFloatConstants, + + kCount, + kSystemConstantCount = kSystemConstantLast - kSystemConstantFirst + 1, + }; + struct RdefConstant { + 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_; + + enum class RdefConstantBufferIndex { + kSystemConstants, + kBoolLoopConstants, + kFetchConstants, + kFloatConstants, + + kCount + }; + struct RdefConstantBuffer { + const char* name; + RdefConstantIndex first_constant; + uint32_t constant_count; + uint32_t size; + uint32_t register_index; + uint32_t binding_count; + bool dynamic_indexed; + }; + static const RdefConstantBuffer + rdef_constant_buffers[size_t(RdefConstantBufferIndex::kCount)]; }; } // namespace gpu