From b46a0c285f14ca67799ce4bb82125b2d0a9deba0 Mon Sep 17 00:00:00 2001 From: Triang3l Date: Wed, 29 Aug 2018 21:54:22 +0300 Subject: [PATCH] [D3D12] DXBC input signature --- src/xenia/gpu/dxbc_shader_translator.cc | 99 +++++++++++++++++++++++++ src/xenia/gpu/dxbc_shader_translator.h | 22 ++++++ 2 files changed, 121 insertions(+) diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index c57889145..645565f36 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -9,6 +9,7 @@ #include "xenia/gpu/dxbc_shader_translator.h" +#include #include #include "third_party/dxbc/DXBCChecksum.h" @@ -63,6 +64,16 @@ std::vector DxbcShaderTranslator::CompleteTranslation() { (uint32_t(shader_object_.size()) - chunk_position_dwords - 2) * sizeof(uint32_t); + // Write Input SiGNature. + chunk_position_dwords = uint32_t(shader_object_.size()); + shader_object_[91] = chunk_position_dwords * sizeof(uint32_t); + shader_object_.push_back('NGSI'); + shader_object_.push_back(0); + WriteInputSignature(); + shader_object_[chunk_position_dwords + 1] = + (uint32_t(shader_object_.size()) - chunk_position_dwords - 2) * + sizeof(uint32_t); + // Fill the remaining fields of the header and copy bytes out. uint32_t shader_object_size = uint32_t(shader_object_.size() * sizeof(uint32_t)); @@ -361,5 +372,93 @@ void DxbcShaderTranslator::WriteResourceDefinitions() { } } +void DxbcShaderTranslator::WriteInputSignature() { + uint32_t chunk_position_dwords = uint32_t(shader_object_.size()); + uint32_t new_offset; + + const uint32_t signature_position_dwords = 2; + const uint32_t signature_size_dwords = 6; + + if (is_vertex_shader()) { + // Only unswapped vertex index. + shader_object_.push_back(1); + // Unknown. + shader_object_.push_back(8); + + // Vertex index. + // Semantic name SV_VertexID (the only one in the signature). + shader_object_.push_back( + (signature_position_dwords + signature_size_dwords) * sizeof(uint32_t)); + // Semantic index. + shader_object_.push_back(0); + // D3D_NAME_VERTEX_ID. + shader_object_.push_back(6); + // D3D_REGISTER_COMPONENT_UINT32. + shader_object_.push_back(1); + shader_object_.push_back(kVSInVertexIndexRegister); + // x present, x used (always written to GPR 0). + shader_object_.push_back(0x1 | (0x1 << 8)); + + // Vertex index semantic name. + AppendString(shader_object_, "SV_VertexID"); + } else { + assert_true(is_pixel_shader()); + // Interpolators, point parameters (coordinates, size), screen position. + shader_object_.push_back(kInterpolatorCount + 2); + // Unknown. + shader_object_.push_back(8); + + // Intepolators. + for (uint32_t i = 0; i < kInterpolatorCount; ++i) { + // Reserve space for the semantic name (TEXCOORD). + shader_object_.push_back(0); + shader_object_.push_back(i); + // D3D_NAME_UNDEFINED. + shader_object_.push_back(0); + // D3D_REGISTER_COMPONENT_FLOAT32. + shader_object_.push_back(3); + shader_object_.push_back(kPSInInterpolatorRegister + i); + // Interpolators are copied to GPRs in the beginning of the shader. If + // there's a register to copy to, this interpolator is used. + shader_object_.push_back(0xF | (i < register_count() ? (0xF << 8) : 0)); + } + + // Point parameters - coordinate on the point and point size as a float3 + // TEXCOORD. Always used because ps_param_gen is handled dynamically. + shader_object_.push_back(0); + shader_object_.push_back(kPointParametersTexCoord); + shader_object_.push_back(0); + shader_object_.push_back(3); + shader_object_.push_back(kPSInPointParametersRegister); + shader_object_.push_back(0x7 | (0x7 << 8)); + + // Position (only XY). Always used because ps_param_gen is handled + // dynamically. + shader_object_.push_back(0); + shader_object_.push_back(0); + // D3D_NAME_POSITION. + shader_object_.push_back(1); + shader_object_.push_back(3); + shader_object_.push_back(kPSInPositionRegister); + shader_object_.push_back(0xF | (0xF << 8)); + + // Write the semantic names. + new_offset = (uint32_t(shader_object_.size()) - chunk_position_dwords) * + sizeof(uint32_t); + for (uint32_t i = 0; i < kInterpolatorCount + 1; ++i) { + uint32_t texcoord_name_position_dwords = chunk_position_dwords + + signature_position_dwords + + i * signature_size_dwords; + shader_object_[texcoord_name_position_dwords] = new_offset; + } + new_offset += AppendString(shader_object_, "TEXCOORD"); + uint32_t position_name_position_dwords = + chunk_position_dwords + signature_position_dwords + + (kInterpolatorCount + 1) * signature_size_dwords; + shader_object_[position_name_position_dwords] = new_offset; + new_offset += AppendString(shader_object_, "POSITION"); + } +} + } // namespace gpu } // namespace xe diff --git a/src/xenia/gpu/dxbc_shader_translator.h b/src/xenia/gpu/dxbc_shader_translator.h index 706870558..eb44f6340 100644 --- a/src/xenia/gpu/dxbc_shader_translator.h +++ b/src/xenia/gpu/dxbc_shader_translator.h @@ -76,10 +76,32 @@ class DxbcShaderTranslator : public ShaderTranslator { kFloatConstantsLast = kFloatConstantsFirst + kFloatConstantPageCount - 1, }; + static constexpr uint32_t kInterpolatorCount = 16; + static constexpr uint32_t kPointParametersTexCoord = kInterpolatorCount; + + // IF ANY OF THESE ARE CHANGED, WriteInputSignature and WriteOutputSignature + // MUST BE UPDATED! + + static constexpr uint32_t kVSInVertexIndexRegister = 0; + static constexpr uint32_t kVSOutInterpolatorRegister = 0; + static constexpr uint32_t kVSOutPointParametersRegister = + kVSOutInterpolatorRegister + kInterpolatorCount; + static constexpr uint32_t kVSOutPositionRegister = + kVSOutPointParametersRegister + 1; + + static constexpr uint32_t kPSInInterpolatorRegister = 0; + static constexpr uint32_t kPSInPointParametersRegister = + kPSInInterpolatorRegister + kInterpolatorCount; + static constexpr uint32_t kPSInPositionRegister = + kPSInPointParametersRegister + 1; + static constexpr uint32_t kPSOutColorRegister = 0; + static constexpr uint32_t kPSOutDepthRegister = kPSOutColorRegister + 4; + // Appends a string to a DWORD stream, returns the DWORD-aligned length. static uint32_t AppendString(std::vector& dest, const char* source); void WriteResourceDefinitions(); + void WriteInputSignature(); // Executable instructions - generated during translation. std::vector shader_code_;