From 4b44d3ce39ae80017dc6b5e3484239f1999700c5 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 2 Apr 2018 19:41:22 +0200 Subject: [PATCH] [dxbc] Unify constants Identical constants will now be reused. Considerably reduces code size. --- src/spirv/spirv_module.cpp | 203 ++++++++++++++++++------------------- src/spirv/spirv_module.h | 6 ++ 2 files changed, 106 insertions(+), 103 deletions(-) diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index d347bf5df..2b01a5a6e 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -1,3 +1,5 @@ +#include + #include "spirv_module.h" namespace dxvk { @@ -136,91 +138,89 @@ namespace dxvk { uint32_t SpirvModule::constBool( bool v) { - uint32_t typeId = this->defBoolType(); - uint32_t resultId = this->allocateId(); - - m_typeConstDefs.putIns (v ? spv::OpConstantTrue : spv::OpConstantFalse, 3); - m_typeConstDefs.putWord (typeId); - m_typeConstDefs.putWord (resultId); - return resultId; + return this->defConst(v + ? spv::OpConstantTrue + : spv::OpConstantFalse, + this->defBoolType(), + 0, nullptr); } uint32_t SpirvModule::consti32( int32_t v) { - uint32_t typeId = this->defIntType(32, 1); - uint32_t resultId = this->allocateId(); + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); - m_typeConstDefs.putIns (spv::OpConstant, 4); - m_typeConstDefs.putWord (typeId); - m_typeConstDefs.putWord (resultId); - m_typeConstDefs.putInt32(v); - return resultId; + return this->defConst( + spv::OpConstant, + this->defIntType(32, 1), + data.size(), + data.data()); } uint32_t SpirvModule::consti64( int64_t v) { - uint32_t typeId = this->defIntType(64, 1); - uint32_t resultId = this->allocateId(); + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); - m_typeConstDefs.putIns (spv::OpConstant, 5); - m_typeConstDefs.putWord (typeId); - m_typeConstDefs.putWord (resultId); - m_typeConstDefs.putInt64(v); - return resultId; + return this->defConst( + spv::OpConstant, + this->defIntType(64, 1), + data.size(), + data.data()); } uint32_t SpirvModule::constu32( uint32_t v) { - uint32_t typeId = this->defIntType(32, 0); - uint32_t resultId = this->allocateId(); + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); - m_typeConstDefs.putIns (spv::OpConstant, 4); - m_typeConstDefs.putWord (typeId); - m_typeConstDefs.putWord (resultId); - m_typeConstDefs.putInt32(v); - return resultId; + return this->defConst( + spv::OpConstant, + this->defIntType(32, 0), + data.size(), + data.data()); } uint32_t SpirvModule::constu64( uint64_t v) { - uint32_t typeId = this->defIntType(64, 0); - uint32_t resultId = this->allocateId(); + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); - m_typeConstDefs.putIns (spv::OpConstant, 5); - m_typeConstDefs.putWord (typeId); - m_typeConstDefs.putWord (resultId); - m_typeConstDefs.putInt64(v); - return resultId; + return this->defConst( + spv::OpConstant, + this->defIntType(64, 0), + data.size(), + data.data()); } uint32_t SpirvModule::constf32( float v) { - uint32_t typeId = this->defFloatType(32); - uint32_t resultId = this->allocateId(); + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); - m_typeConstDefs.putIns (spv::OpConstant, 4); - m_typeConstDefs.putWord (typeId); - m_typeConstDefs.putWord (resultId); - m_typeConstDefs.putFloat32(v); - return resultId; + return this->defConst( + spv::OpConstant, + this->defFloatType(32), + data.size(), + data.data()); } uint32_t SpirvModule::constf64( double v) { - uint32_t typeId = this->defFloatType(64); - uint32_t resultId = this->allocateId(); + std::array data; + std::memcpy(data.data(), &v, sizeof(v)); - m_typeConstDefs.putIns (spv::OpConstant, 5); - m_typeConstDefs.putWord (typeId); - m_typeConstDefs.putWord (resultId); - m_typeConstDefs.putFloat64(v); - return resultId; + return this->defConst( + spv::OpConstant, + this->defFloatType(64), + data.size(), + data.data()); } @@ -229,24 +229,15 @@ namespace dxvk { int32_t y, int32_t z, int32_t w) { + std::array args = {{ + this->consti32(x), this->consti32(y), + this->consti32(z), this->consti32(w), + }}; + uint32_t scalarTypeId = this->defIntType(32, 1); uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); - uint32_t resultId = this->allocateId(); - - uint32_t xConst = this->consti32(x); - uint32_t yConst = this->consti32(y); - uint32_t zConst = this->consti32(z); - uint32_t wConst = this->consti32(w); - - m_typeConstDefs.putIns (spv::OpConstantComposite, 7); - m_typeConstDefs.putWord (vectorTypeId); - m_typeConstDefs.putWord (resultId); - m_typeConstDefs.putWord (xConst); - m_typeConstDefs.putWord (yConst); - m_typeConstDefs.putWord (zConst); - m_typeConstDefs.putWord (wConst); - return resultId; + return this->constComposite(vectorTypeId, args.size(), args.data()); } @@ -255,24 +246,15 @@ namespace dxvk { uint32_t y, uint32_t z, uint32_t w) { + std::array args = {{ + this->constu32(x), this->constu32(y), + this->constu32(z), this->constu32(w), + }}; + uint32_t scalarTypeId = this->defIntType(32, 0); uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); - uint32_t resultId = this->allocateId(); - - uint32_t xConst = this->constu32(x); - uint32_t yConst = this->constu32(y); - uint32_t zConst = this->constu32(z); - uint32_t wConst = this->constu32(w); - - m_typeConstDefs.putIns (spv::OpConstantComposite, 7); - m_typeConstDefs.putWord (vectorTypeId); - m_typeConstDefs.putWord (resultId); - m_typeConstDefs.putWord (xConst); - m_typeConstDefs.putWord (yConst); - m_typeConstDefs.putWord (zConst); - m_typeConstDefs.putWord (wConst); - return resultId; + return this->constComposite(vectorTypeId, args.size(), args.data()); } @@ -281,24 +263,15 @@ namespace dxvk { float y, float z, float w) { + std::array args = {{ + this->constf32(x), this->constf32(y), + this->constf32(z), this->constf32(w), + }}; + uint32_t scalarTypeId = this->defFloatType(32); uint32_t vectorTypeId = this->defVectorType(scalarTypeId, 4); - uint32_t resultId = this->allocateId(); - - uint32_t xConst = this->constf32(x); - uint32_t yConst = this->constf32(y); - uint32_t zConst = this->constf32(z); - uint32_t wConst = this->constf32(w); - - m_typeConstDefs.putIns (spv::OpConstantComposite, 7); - m_typeConstDefs.putWord (vectorTypeId); - m_typeConstDefs.putWord (resultId); - m_typeConstDefs.putWord (xConst); - m_typeConstDefs.putWord (yConst); - m_typeConstDefs.putWord (zConst); - m_typeConstDefs.putWord (wConst); - return resultId; + return this->constComposite(vectorTypeId, args.size(), args.data()); } @@ -306,15 +279,9 @@ namespace dxvk { uint32_t typeId, uint32_t constCount, const uint32_t* constIds) { - uint32_t resultId = this->allocateId(); - - m_typeConstDefs.putIns (spv::OpConstantComposite, 3 + constCount); - m_typeConstDefs.putWord (typeId); - m_typeConstDefs.putWord (resultId); - - for (uint32_t i = 0; i < constCount; i++) - m_typeConstDefs.putWord(constIds[i]); - return resultId; + return this->defConst( + spv::OpConstantComposite, + typeId, constCount, constIds); } @@ -2929,6 +2896,36 @@ namespace dxvk { } + uint32_t SpirvModule::defConst( + spv::Op op, + uint32_t typeId, + uint32_t argCount, + const uint32_t* argIds) { + // Avoid declaring constants multiple times + for (auto ins : m_typeConstDefs) { + bool match = ins.opCode() == op + && ins.length() == 3 + argCount + && ins.arg(1) == typeId; + + for (uint32_t i = 0; i < argCount && match; i++) + match &= ins.arg(3 + i) == argIds[i]; + + if (match) + return ins.arg(2); + } + + // Constant not yet declared, make a new one + uint32_t resultId = this->allocateId(); + m_typeConstDefs.putIns (op, 3 + argCount); + m_typeConstDefs.putWord(typeId); + m_typeConstDefs.putWord(resultId); + + for (uint32_t i = 0; i < argCount; i++) + m_typeConstDefs.putWord(argIds[i]); + return resultId; + } + + void SpirvModule::instImportGlsl450() { m_instExtGlsl450 = this->allocateId(); const char* name = "GLSL.std.450"; diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 041b60128..9819c9c8d 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -1022,6 +1022,12 @@ namespace dxvk { uint32_t argCount, const uint32_t* argIds); + uint32_t defConst( + spv::Op op, + uint32_t typeId, + uint32_t argCount, + const uint32_t* argIds); + void instImportGlsl450(); uint32_t getImageOperandWordCount(