diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index bfbf95f41..2b1b0c9c3 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -14,6 +14,7 @@ #include "third_party/dxbc/DXBCChecksum.h" #include "third_party/dxbc/d3d12TokenizedProgramFormat.hpp" +#include "xenia/base/assert.h" #include "xenia/base/math.h" namespace xe { @@ -34,15 +35,31 @@ std::vector DxbcShaderTranslator::CompleteTranslation() { // Write the shader object header. shader_object_.push_back('CBXD'); - // Reserve space for the checksum. + // Checksum (set later). for (uint32_t i = 0; i < 4; ++i) { shader_object_.push_back(0); } shader_object_.push_back(1); - // Reserve space for the size. + // Size (set later). shader_object_.push_back(0); // 5 chunks - RDEF, ISGN, OSGN, SHEX, STAT. shader_object_.push_back(5); + // Chunk offsets (set later). + for (uint32_t i = 0; i < shader_object_[7]; ++i) { + shader_object_.push_back(0); + } + + uint32_t chunk_position_dwords; + + // Write Resource DEFinitions. + chunk_position_dwords = uint32_t(shader_object_.size()); + shader_object_[8] = chunk_position_dwords * sizeof(uint32_t); + shader_object_.push_back('FEDR'); + shader_object_.push_back(0); + WriteResourceDefinitions(); + 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 = @@ -64,13 +81,61 @@ uint32_t DxbcShaderTranslator::AppendString(std::vector& dest, const char* source) { size_t size = std::strlen(source) + 1; size_t size_aligned = xe::align(size_aligned, sizeof(uint32_t)); - size_t dest_pos = dest.size(); - dest.resize(dest_pos + size_aligned / sizeof(uint32_t)); - std::memcpy(&dest[dest_pos], source, size); - std::memset(reinterpret_cast(&dest[dest_pos]) + size, 0xAB, + size_t dest_position = dest.size(); + dest.resize(dest_position + size_aligned / sizeof(uint32_t)); + std::memcpy(&dest[dest_position], source, size); + std::memset(reinterpret_cast(&dest[dest_position]) + size, 0xAB, size_aligned - size); return uint32_t(size_aligned); } +void DxbcShaderTranslator::WriteResourceDefinitions() { + uint32_t chunk_position_dwords = uint32_t(shader_object_.size()); + + // Write the 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); + // 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); + // TODO(Triang3l): Bound resource buffer offset (set later). + shader_object_.push_back(0); + if (is_vertex_shader()) { + // vs_5_1 + shader_object_.push_back(0xFFFE0501u); + } else { + assert_true(is_pixel_shader()); + // ps_5_1 + shader_object_.push_back(0xFFFF0501u); + } + // Compiler flags - default for SM 5.1 (no preshader, prefer flow control). + shader_object_.push_back(0x500); + // Generator offset (directly after the RDEF header in our case). + shader_object_.push_back(60); + // RD11, but with nibbles inverted (unlike in SM 5.0). + shader_object_.push_back(0x25441313); + // Unknown fields. + shader_object_.push_back(60); + shader_object_.push_back(24); + // Was 32 in SM 5.0. + shader_object_.push_back(40); + shader_object_.push_back(40); + shader_object_.push_back(36); + shader_object_.push_back(12); + shader_object_.push_back(0); + // 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); +} + } // namespace gpu } // namespace xe diff --git a/src/xenia/gpu/dxbc_shader_translator.h b/src/xenia/gpu/dxbc_shader_translator.h index b8d3ad381..509f7145e 100644 --- a/src/xenia/gpu/dxbc_shader_translator.h +++ b/src/xenia/gpu/dxbc_shader_translator.h @@ -32,6 +32,8 @@ class DxbcShaderTranslator : public ShaderTranslator { // Appends a string to a DWORD stream, returns the DWORD-aligned length. static uint32_t AppendString(std::vector& dest, const char* source); + void WriteResourceDefinitions(); + // Executable instructions - generated during translation. std::vector shader_code_; // Complete shader object, with all the needed chunks and dcl_ instructions -