示例#1
0
Root::Root(Number& base, Number& root) {
	this->base = &base;
	this->root = &root;
	
	if (typeid(*this->root) == typeid(Placeholder) && (typeid(*this->base) == typeid(Placeholder) || typeid(*this->base) == typeid(Integer))) {
		Placeholder * cast = dynamic_cast<Placeholder*>(this->root);
		for (int i = 0; i < cast->getOperators().size(); i++) {
			if (cast->getOperators().at(i) == '/') {
				if (typeid(cast->getNumbers().at(i + 1)) == typeid(Integer)) {
					Integer * intCast = dynamic_cast<Integer*>(cast->getNumbers().at(i + 1));

					if (typeid(*this->base) == typeid(Placeholder)) {
						Placeholder * baseCast = dynamic_cast<Placeholder*>(this->base);
						for (int x = 0; x < baseCast->getNumbers().size(); x++) {
							if (typeid(*baseCast->getNumbers().at(x)) == typeid(Integer)) {
								Integer * baseInt = dynamic_cast<Integer*>(baseCast->getNumbers().at(x));
								if (intCast->getInt() % 2 == 0 && baseInt < 0) {
									throw std::out_of_range("A negative number cannot be applied to an even root. SOURCE: " + this->toString());
								}
							}
						}
					}
					else if (typeid(*this->base) == typeid(Integer)) {
						Integer * baseInt = dynamic_cast<Integer*>(this->base);
						if (intCast->getInt() % 2 == 0 && baseInt < 0) {
							throw std::out_of_range("A negative number cannot be applied to an even root. SOURCE: " + this->toString());
						}
					}
				}
			}
		}
	}
}
示例#2
0
Number& Root::simplify(){
	if (typeid(*base) == typeid(Integer) && typeid(*root) == typeid(Integer)) {
		Integer * baseInt = dynamic_cast<Integer*>(base);
		Integer * rootInt = dynamic_cast<Integer*>(root);

		bool isRootNeg = false;
		bool isBaseNeg = false;

		if (rootInt->getInt() < 0) {
			isRootNeg = true;
			int newRoot = rootInt->getInt() * -1;
			delete rootInt;
			root = new Integer(newRoot);
			rootInt = new Integer(newRoot);
		}
		else if (rootInt->getInt() == 0) {
			throw std::out_of_range("The value of n for an n'th root object cannot be 0. SOURCE: " + this->toString());
		}

		if (baseInt->getInt() < 0 && rootInt->getInt() % 2 != 0) {
			isBaseNeg = true;
			int newBase = baseInt->getInt() * -1;
			delete baseInt;
			base = new Integer(newBase);
			baseInt = new Integer(newBase);
		}
		else if (baseInt->getInt() == 0) {
			return *(new Integer(0));
		}
		else if (baseInt->getInt() < 0 && rootInt->getInt() % 2 == 0) {
			throw std::out_of_range("A negative number cannot be applied to an even root. SOURCE: " + this->toString());
		}
		
		std::vector<int*> vec = primeFactors(baseInt->getInt());

		double invRoot = 1 / ((double)rootInt->getInt());

		if ((int)pow(baseInt->getInt(), invRoot) == pow(baseInt->getInt(), invRoot)) {
			if (isRootNeg) {
				Integer * one = new Integer(1);
				Placeholder * ph = new Placeholder();
				ph->getNumbers().push_back(one);
				if (isBaseNeg) {
					ph->getNumbers().push_back(new Integer(pow(baseInt->getInt(), invRoot) * -1));
				}
				else {
					ph->getNumbers().push_back(new Integer(pow(baseInt->getInt(), invRoot)));
				}
				ph->getOperators().push_back('/');
				return *ph;
			}
			if (isBaseNeg) {
				Number * toReturn = (new Integer(pow(baseInt->getInt(), invRoot) * -1));
				return *toReturn;
			}
			else {
				Number * toReturn = (new Integer(pow(baseInt->getInt(), invRoot)));
				return *toReturn;
			}
		}

		int multiplier = 1;
		int innerValue = 1;

		for (int i = 1; i < vec.size(); i++) {
			int exp = vec.at(i)[1];
			int multiplierExp = 0;
			for (int x = 0; x < vec.at(i)[1]; x++) {
				if (exp - rootInt->getInt() >= 0) {
					exp = exp - rootInt->getInt();
					multiplierExp++;
				} else {
					x = vec.at(i)[1];
				}
			}

			vec.at(i)[1] = exp;
			multiplier *= pow(vec.at(i)[0], multiplierExp);
			innerValue *= pow(vec.at(i)[0], vec.at(i)[1]);
		}

		if (multiplier > 1) {
			if (innerValue == 1) {
				Number * toReturn = new Integer(multiplier);
				return *toReturn;
			}

			if (isRootNeg) {
				Integer * one = NULL;

				if (isBaseNeg) {
					one = new Integer(1);
				}
				else {
					one = new Integer(-1);
				}

				Placeholder * simplified = new Placeholder();
				simplified->getNumbers().push_back(new Integer(multiplier));
				delete base;
				this->base = new Integer(innerValue);
				simplified->getNumbers().push_back(&this->clone());
				simplified->getOperators().push_back('*');

				Placeholder * ph = new Placeholder();
				ph->getNumbers().push_back(one);
				ph->getNumbers().push_back(simplified);
				ph->getOperators().push_back('/');
				return *ph;
			}

			Placeholder * simplified = new Placeholder();
			if (isBaseNeg) {
				simplified->getNumbers().push_back(new Integer(multiplier * -1));
			}
			else {
				simplified->getNumbers().push_back(new Integer(multiplier));
			}
			delete base;
			this->base = new Integer(innerValue);
			simplified->getNumbers().push_back(&this->clone());
			simplified->getOperators().push_back('*');
			return *simplified;
		}

		return this->clone();
	} else if (typeid(*root) == typeid(Placeholder)) {
		Placeholder * rootPlaceholder = dynamic_cast<Placeholder*>(root);
		if (typeid(rootPlaceholder->getNumbers().at(0)) == typeid(Integer)) {
			Integer * negRootInt = dynamic_cast<Integer*>(rootPlaceholder->getNumbers().at(0));
			Integer * rootInt = dynamic_cast<Integer*>(rootPlaceholder->getNumbers().at(1));
			if (negRootInt->getInt() == -1) {
				Placeholder * ph = new Placeholder();
				Integer * one = new Integer(1);

				ph->getNumbers().push_back(one);
				ph->getNumbers().push_back(&rootInt->clone());
				ph->getOperators().push_back('/');
				Exponent * exp = new Exponent(base->clone(), *ph);
				return *exp;
			} else {
				return this->clone();
			}
		} else {
			return this->clone();
		}
	} else if (typeid(*base) == typeid(Placeholder)) {
		Placeholder * basePlaceholder = dynamic_cast<Placeholder*>(base);
		if (typeid(basePlaceholder->getNumbers().at(0)) == typeid(Integer)) {
			Integer * negBaseInt = dynamic_cast<Integer*>(basePlaceholder->getNumbers().at(0));
			if (typeid(*root) == typeid(Integer)) {
				Integer * rootInt = dynamic_cast<Integer*>(root);
				if (negBaseInt->getInt() < 0 && rootInt->getInt() % 2 == 0) {
					throw std::out_of_range("A negative number cannot be applied to an even root. SOURCE: " + this->toString());
				}
			}
		}
	} else {
		return this->clone();
	}
}
示例#3
0
// **NOTICE**: In order to avoid circular referencing, this method must be copy and pasted as opposed to
// being inherited from the Number class.
bool Root::operator==(Number& rhs) {
	if (typeid(*this) == typeid(rhs)) {
		if (typeid(rhs) == typeid(Exponent)) {
			Exponent * rhsCast = dynamic_cast<Exponent*>(&rhs);
			Exponent * lhsCast = dynamic_cast<Exponent*>(this);
			if (rhsCast->getBase() == lhsCast->getBase() && rhsCast->getExponent() == lhsCast->getExponent()) {
				return true;
			} else {
				return false;
			}
		} else if (typeid(rhs) == typeid(Log)) {
			Log * rhsCast = dynamic_cast<Log*>(&rhs);
			Log * lhsCast = dynamic_cast<Log*>(this);
			if (rhsCast->getBase() == lhsCast->getBase() && rhsCast->getArgument() == lhsCast->getArgument()) {
				return true;
			} else {
				return false;
			}
		} else if (typeid(rhs) == typeid(Placeholder)) {
			Placeholder * rhsCast = dynamic_cast<Placeholder*>(&rhs);
			Placeholder * lhsCast = dynamic_cast<Placeholder*>(this);

			if (rhsCast->getNumbers().size() == lhsCast->getNumbers().size()) {
				for (int i = 0; i < lhsCast->getNumbers().size(); i++) {
					bool matched = false;

					for (int y = 0; y < rhsCast->getNumbers().size(); y++) {
						if (lhsCast[i] == rhsCast[y]) {
							matched = true;
						}
					}

					if (!matched) {
						return false;
					}
				}

				for (int i = 0; i < lhsCast->getOperators().size(); i++) {
					bool matched = false;

					for (int y = 0; y < rhsCast->getOperators().size(); y++) {
						if (lhsCast->getOperators()[i] == rhsCast->getOperators()[y]) {
							if (lhsCast->getOperators()[i] == '-' || lhsCast->getOperators()[i] == '/') {
								if (lhsCast->getNumbers()[i] == rhsCast->getNumbers()[y] && lhsCast->getNumbers()[i+1] == rhsCast->getNumbers()[y+1]) {
									matched = true;
								} else {
									matched = false;
								}
							} else {
								if (lhsCast->getNumbers()[i] == rhsCast->getNumbers()[y] && lhsCast->getNumbers()[i+1] == rhsCast->getNumbers()[y+1]) {
									matched = true;
								} else if (lhsCast->getNumbers()[i+1] == rhsCast->getNumbers()[y] && lhsCast->getNumbers()[i] == rhsCast->getNumbers()[y+1]) {
									matched = true;
								} else {
									matched = false;
								}
							}
						}
					}

					if (!matched) {
						return false;
					}
				}

				return true;
			} else {
				return false;
			}
		} else if (typeid(rhs) == typeid(Root)) {
			Root * rhsCast = dynamic_cast<Root*>(&rhs);
			Root * lhsCast = dynamic_cast<Root*>(this);
			if (rhsCast->getBase() == lhsCast->getBase() && rhsCast->getRoot() == lhsCast->getRoot()) {
				return true;
			} else {
				return false;
			}
		} else if (typeid(rhs) == typeid(Integer)) {
			Integer * rhsCast = dynamic_cast<Integer*>(&rhs);
			Integer * lhsCast = dynamic_cast<Integer*>(this);

			if (rhsCast->getInt() == lhsCast->getInt()) {
				return true;
			} else {
				return false;
			}
		} else if (typeid(rhs) == typeid(Variable)) {
			Variable * rhsCast = dynamic_cast<Variable*>(&rhs);
			Variable * lhsCast = dynamic_cast<Variable*>(this);

			if (lhsCast->getVariable() == rhsCast->getVariable()) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	} else {
		return false;
	}
}
Number& Placeholder::operator+(Number& rhs) {
	if (typeid(rhs) == typeid(Placeholder)) {
		Placeholder * rhsCast = dynamic_cast<Placeholder*>(&rhs);
		std::vector<Number*> rhsNumberList = rhsCast->getNumbers();
		std::vector<char> rhsOperatorList = rhsCast->getOperators();

		for (int i = 0; i < rhsNumberList.capacity(); i++) {
			Number * addition = &(*this + *rhsNumberList[i]);

			if (typeid(addition) == typeid(Placeholder)) {
				Placeholder * tempPlaceholder = dynamic_cast<Placeholder*>(addition);
				this->numbers = &tempPlaceholder->getNumbers();
				this->operators = &tempPlaceholder->getOperators();
			} else {
				this->numbers->clear();
				this->operators->clear();
				this->numbers->push_back(addition);
			}
		}

		if (this->numbers->capacity() == 1) {
			return *this->numbers->at(0);
		} else {
			return *this;
		}

	} else if (typeid(rhs) == typeid(Exponent)) {
		Exponent * rhsCast = dynamic_cast<Exponent*>(&rhs);

		for (int i = 0; i < this->numbers->capacity(); i++) {
			if (i != 0 && this->operators->at(i-1) == '/') {
				break;
			} else if ((i == 0 && this->operators->at(0) == '/') || (i != 0 && this->operators->at(i - 1) == '/')) {
				Number * toAdd = &(*this->numbers->at(i + 1) * *rhsCast);
				Number * result = &(*this->numbers->at(i) + *toAdd);
				return *result;
			} else if (typeid(this->numbers[i]) == typeid(Exponent)) {
				Exponent * lhsCast = dynamic_cast<Exponent*>(this->numbers->at(i));

				if (this->operators->at(i) == '*' || (i != 0 && this->operators->at(i-1) == '*')) {
					this->numbers->push_back(&rhs);
					this->operators->push_back('+');
					delete rhsCast;
					delete lhsCast;
					return *this;
				} else if (lhsCast->getBase() == rhsCast->getBase() && lhsCast->getExponent() == rhsCast->getExponent()){
					this->numbers->insert(this->numbers->begin() + i - 1, new Integer(2));
					this->operators->insert(this->operators->begin() + i - 2, '*');
					delete rhsCast;
					delete lhsCast;
					return *this;
				}
			} else if (i == this->numbers->capacity() - 1) {
				this->numbers->push_back(&rhs);
				this->operators->push_back('+');
				delete rhsCast;
				return *this;
			}
		}

	} else if (typeid(rhs) == typeid(Integer)) {
		Integer * rhsCast = dynamic_cast<Integer*>(&rhs);

		for (int i = 0; i < this->numbers->capacity(); i++) {
			if (i != 0 && this->operators->at(i-1) == '/') {
				break;
			} else if ((i == 0 && this->operators->at(0) == '/') || (i != 0 && this->operators->at(i - 1) == '/')) {
				Number * toAdd = &(*this->numbers->at(i + 1) * *rhsCast);
				Number * result = &(*this->numbers->at(i) + *toAdd);
				return *result;
			} else if (typeid(this->numbers[i]) == typeid(Exponent)) {
				Integer * lhsCast = dynamic_cast<Integer*>(this->numbers->at(i));

				this->numbers->assign(i, new Integer(lhsCast->getInt() + rhsCast->getInt()));
				return *this;
			} else if (i == this->numbers->capacity() - 1) {
				this->numbers->push_back(&rhs);
				this->operators->push_back('+');
				delete rhsCast;
				return *this;
			}
		}

	} else if (typeid(rhs) == typeid(Log)) {
		Log * rhsCast = dynamic_cast<Log*>(&rhs);

		for (int i = 0; i < this->numbers->capacity(); i++) {
			if (i != 0 && this->operators->at(i-1) == '/') {
				break;
			} else if ((i == 0 && this->operators->at(0) == '/') || (i != 0 && this->operators->at(i - 1) == '/')) {
				Number * toAdd = &(*this->numbers->at(i + 1) * *rhsCast);
				Number * result = &(*this->numbers->at(i) + *toAdd);
				return *result;
			} else if (typeid(this->numbers[i]) == typeid(Log)) {
				Log * lhsCast = dynamic_cast<Log*>(this->numbers->at(i));

				if (this->operators->at(i) == '*' || (i != 0 && this->operators->at(i-1) == '*')) {
					this->numbers->push_back(&rhs);
					this->operators->push_back('+');
					delete rhsCast;
					delete lhsCast;
					return *this;
				} else if (lhsCast->getBase() == rhsCast->getBase() && lhsCast->getArgument() == rhsCast->getArgument()){
					this->numbers->insert(this->numbers->begin() + i - 1, new Integer(2));
					this->operators->insert(this->operators->begin() + i - 2, '*');
					delete rhsCast;
					delete lhsCast;
					return *this;
				}
			} else if (i == this->numbers->capacity() - 1) {
				this->numbers->push_back(&rhs);
				this->operators->push_back('+');
				delete rhsCast;
				return *this;
			}
		}

	} else if (typeid(rhs) == typeid(Root)) {
		Root * rhsCast = dynamic_cast<Root*>(&rhs);

		for (int i = 0; i < this->numbers->capacity(); i++) {
			if (i != 0 && this->operators->at(i-1) == '/') {
				break;
			} else if ((i == 0 && this->operators->at(0) == '/') || (i != 0 && this->operators->at(i - 1) == '/')) {
				Number * toAdd = &(*this->numbers->at(i + 1) * *rhsCast);
				Number * result = &(*this->numbers->at(i) + *toAdd);
				return *result;
			} else if (typeid(this->numbers[i]) == typeid(Root)) {
				Root * lhsCast = dynamic_cast<Root*>(this->numbers->at(i));

				if (this->operators->at(i) == '*' || (i != 0 && this->operators->at(i-1) == '*')) {
					this->numbers->push_back(&rhs);
					this->operators->push_back('+');
					delete rhsCast;
					delete lhsCast;
					return *this;
				} else if (lhsCast->getBase() == rhsCast->getBase() && lhsCast->getRoot() == rhsCast->getRoot()){
					this->numbers->insert(this->numbers->begin() + i - 1, new Integer(2));
					this->operators->insert(this->operators->begin() + i - 2, '*');
					delete rhsCast;
					delete lhsCast;
					return *this;
				}
			} else if (i == this->numbers->capacity() - 1) {
				this->numbers->push_back(&rhs);
				this->operators->push_back('+');
				delete rhsCast;
				return *this;
			}
		}

	} else if (typeid(rhs) == typeid(Variable)) {
		Variable * rhsCast = dynamic_cast<Variable*>(&rhs);

		for (int i = 0; i < this->numbers->capacity(); i++) {
			if (i != 0 && this->operators->at(i-1) == '/') {
				break;
			} else if ((i == 0 && this->operators->at(0) == '/') || (i != 0 && this->operators->at(i - 1) == '/')) {
				Number * toAdd = &(*this->numbers->at(i + 1) * *rhsCast);
				Number * result = &(*this->numbers->at(i) + *toAdd);
				return *result;
			} else if (typeid(this->numbers[i]) == typeid(Variable)) {
				Variable * lhsCast = dynamic_cast<Variable*>(this->numbers->at(i));

				if (this->operators->at(i) == '*' || (i != 0 && this->operators->at(i-1) == '*')) {
					this->numbers->push_back(&rhs);
					this->operators->push_back('+');
					delete rhsCast;
					delete lhsCast;
					return *this;
				} else if (lhsCast->getVariable() == rhsCast->getVariable()){
					this->numbers->insert(this->numbers->begin() + i - 1, new Integer(2));
					this->operators->insert(this->operators->begin() + i - 2, '*');
					delete rhsCast;
					delete lhsCast;
					return *this;
				}
			} else if (i == this->numbers->capacity() - 1) {
				this->numbers->push_back(&rhs);
				this->operators->push_back('+');
				delete rhsCast;
				return *this;
			}
		}

	}
}
示例#5
0
namespace Eigen
{
    static Placeholder<Pool<Texture::Details>>      g_texturePoolPlaceholder;
    static Placeholder<Pool<TargetGroup::Details>>  g_targetGroupPoolPlaceholder;
    static Pool<Texture::Details>&                  g_texturePool = (Pool<Texture::Details>&)g_texturePoolPlaceholder.storage;
    static Pool<TargetGroup::Details>&              g_targetGroupPool = (Pool<TargetGroup::Details>&)g_targetGroupPoolPlaceholder.storage;

    static std::atomic<Texture::Details*>           g_textureGarbage;

    static DXGI_FORMAT TranslateFormat(Texture::Format format)
    {
        switch (format)
        {
        case Texture::cFormat_BC1:              return DXGI_FORMAT_BC1_TYPELESS;
        case Texture::cFormat_BC2:              return DXGI_FORMAT_BC2_TYPELESS;
        case Texture::cFormat_BC3:              return DXGI_FORMAT_BC3_TYPELESS;
        case Texture::cFormat_BC4:              return DXGI_FORMAT_BC4_TYPELESS;
        case Texture::cFormat_BC5:              return DXGI_FORMAT_BC5_TYPELESS;
        case Texture::cFormat_BC6:              return DXGI_FORMAT_BC6H_TYPELESS;
        case Texture::cFormat_BC7:              return DXGI_FORMAT_BC7_TYPELESS;
        case Texture::cFormat_RGBA8:            return DXGI_FORMAT_R8G8B8A8_TYPELESS;
        case Texture::cFormat_RGB10_A2:         return DXGI_FORMAT_R10G10B10A2_TYPELESS;
        case Texture::cFormat_RGBA16:           return DXGI_FORMAT_R16G16B16A16_TYPELESS;
        case Texture::cFormat_RGBA16f:          return DXGI_FORMAT_R16G16B16A16_FLOAT;
        case Texture::cFormat_RGBA32f:          return DXGI_FORMAT_R32G32B32A32_FLOAT;
        default:                                return DXGI_FORMAT_UNKNOWN;
        }
    }

    static DXGI_FORMAT TranslateFormat(TextureTarget::Format format)
    {
        switch (format)
        {
        case TextureTarget::cFormat_RGBA8:      return DXGI_FORMAT_R8G8B8A8_UNORM;
        case TextureTarget::cFormat_RGB10_A2:   return DXGI_FORMAT_R10G10B10A2_UNORM;
        case TextureTarget::cFormat_RGBA16:     return DXGI_FORMAT_R16G16B16A16_UNORM;
        case TextureTarget::cFormat_RGBA16f:    return DXGI_FORMAT_R16G16B16A16_FLOAT;
        case TextureTarget::cFormat_RGBA32f:    return DXGI_FORMAT_R32G32B32A32_FLOAT;
        case TextureTarget::cFormat_D24_S8:     return DXGI_FORMAT_D24_UNORM_S8_UINT;
        case TextureTarget::cFormat_D32f:       return DXGI_FORMAT_D32_FLOAT;
        case TextureTarget::cFormat_D32f_S8:    return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
        default:                                return DXGI_FORMAT_UNKNOWN;
        }
    }

    void DescFromTargetParams(D3D11_RENDER_TARGET_VIEW_DESC& desc, const TextureTarget::Params& params, const TextureTarget::Slice& slice, unsigned planes)
    {
        desc.Format = DXGI_FORMAT_UNKNOWN;
        if (params.depth > 0)
        {
            assert(params.arrayLength == 0);
            assert(params.depth >= slice.planeOffset + planes);
            assert(params.multisampling == TextureTarget::cMultisampling_1x);
            desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
            desc.Texture3D.MipSlice = slice.mip;
            desc.Texture3D.FirstWSlice = slice.planeOffset;
            desc.Texture3D.WSize = planes;
        }
        else if (params.arrayLength > 0)
        {
            assert(params.arrayLength >= slice.planeOffset + planes);

            if (params.multisampling == TextureTarget::cMultisampling_1x)
            {
                desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
                desc.Texture2DArray.MipSlice = slice.mip;
                desc.Texture2DArray.FirstArraySlice = slice.planeOffset;
                desc.Texture2DArray.ArraySize = planes;
            }
            else
            {
                assert(slice.mip == 0);
                desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
                desc.Texture2DMSArray.FirstArraySlice = slice.planeOffset;
                desc.Texture2DMSArray.ArraySize = planes;
            }
        }
        else
        {
            if (params.multisampling == TextureTarget::cMultisampling_1x)
            {
                desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
                desc.Texture2D.MipSlice = slice.mip;
            }
            else
            {
                assert(slice.mip == 0);
                desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
            }
        }
    }

    void DescFromTargetParams(D3D11_DEPTH_STENCIL_VIEW_DESC& desc, const TextureTarget::Params& params, const TextureTarget::Slice& slice, unsigned planes)
    {
        desc.Format = DXGI_FORMAT_UNKNOWN;
        if (params.arrayLength > 0 || params.depth > 0)
        {
            assert((params.arrayLength > 0) ^ (params.depth > 0));
            assert(params.arrayLength == 0 || params.arrayLength >= slice.planeOffset + planes);
            assert(params.depth == 0 || params.depth >= slice.planeOffset + planes);

            if (params.multisampling == TextureTarget::cMultisampling_1x)
            {
                desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
                desc.Texture2DArray.MipSlice = slice.mip;
                desc.Texture2DArray.FirstArraySlice = slice.planeOffset;
                desc.Texture2DArray.ArraySize = planes;
            }
            else
            {
                assert(slice.mip == 0);
                desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
                desc.Texture2DMSArray.FirstArraySlice = slice.planeOffset;
                desc.Texture2DMSArray.ArraySize = planes;
            }
        }
        else
        {
            if (params.multisampling == TextureTarget::cMultisampling_1x)
            {
                desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
                desc.Texture2D.MipSlice = slice.mip;
            }
            else
            {
                assert(slice.mip == 0);
                desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
            }
        }
        desc.Flags = 0;
    }

    static bool IsDepthFormat(TextureTarget::Format format)
    {
        return format == TextureTarget::cFormat_D24_S8 || format == TextureTarget::cFormat_D32f || format == TextureTarget::cFormat_D32f_S8;
    }

    TexturePtr TextureSystem::CreateTexture(const Texture::Params& params)
    {
        ComPtr<ID3D11Resource> d3dResource;

        if (params.depth > 0)
        {
            D3D11_TEXTURE3D_DESC desc;
            desc.Width = params.width;
            desc.Height = params.height;
            desc.Depth = params.depth;
            desc.MipLevels = params.lastMip+1;
            desc.Format = TranslateFormat((Texture::Format)params.format);
            desc.Usage = (params.flags & Texture::cFlag_Dynamic) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
            desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
            desc.CPUAccessFlags = (params.flags & Texture::cFlag_Dynamic) ? D3D11_CPU_ACCESS_WRITE : 0;
            desc.MiscFlags = 0;

            HRESULT hr = EngineCore::s_instance.device->CreateTexture3D(&desc, nullptr, (ID3D11Texture3D**) d3dResource.GetAddressOf());
            if (FAILED(hr))
                return nullptr;
        }
        else if (params.height > 0)
        {
            D3D11_TEXTURE2D_DESC desc;
            desc.Width = params.width;
            desc.Height = params.height;
            desc.MipLevels = params.lastMip+1;
            desc.ArraySize = params.arrayLength > 0 ? params.arrayLength : 1;
            desc.Format = TranslateFormat((Texture::Format)params.format);
            desc.SampleDesc.Count = 1;
            desc.SampleDesc.Quality = 0;
            desc.Usage = (params.flags & Texture::cFlag_Dynamic) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
            desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
            desc.CPUAccessFlags = (params.flags & Texture::cFlag_Dynamic) ? D3D11_CPU_ACCESS_WRITE : 0;
            desc.MiscFlags = (params.flags & Texture::cFlag_CubeMap) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;

            HRESULT hr = EngineCore::s_instance.device->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D**) d3dResource.GetAddressOf());
            if (FAILED(hr))
                return nullptr;
        }
        else
        {
            D3D11_TEXTURE1D_DESC desc;
            desc.Width = params.width;
            desc.MipLevels = params.lastMip+1;
            desc.ArraySize = params.arrayLength > 0 ? params.arrayLength : 1;
            desc.Format = TranslateFormat((Texture::Format)params.format);
            desc.Usage = (params.flags & Texture::cFlag_Dynamic) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
            desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
            desc.CPUAccessFlags = (params.flags & Texture::cFlag_Dynamic) ? D3D11_CPU_ACCESS_WRITE : 0;
            desc.MiscFlags = 0;

            HRESULT hr = EngineCore::s_instance.device->CreateTexture1D(&desc, nullptr, (ID3D11Texture1D**) d3dResource.GetAddressOf());
            if (FAILED(hr))
                return nullptr;
        }

        Texture::Details* details = new(g_texturePool.Allocate()) Texture::Details(params);
        assert(details != nullptr);
        details->m_d3dResource.Swap(d3dResource);
        return details;
    }

    TextureTargetPtr TextureSystem::CreateTarget(const TextureTarget::Params& params)
    {
        ComPtr<ID3D11Resource> d3dResource;

        if (params.depth > 0)
        {
            D3D11_TEXTURE3D_DESC desc;
            desc.Width = params.width;
            desc.Height = params.height;
            desc.Depth = params.depth;
            desc.MipLevels = params.lastMip+1;
            desc.Format = TranslateFormat((TextureTarget::Format)params.format);
            desc.Usage = D3D11_USAGE_DEFAULT;
            desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
            desc.BindFlags |= IsDepthFormat((TextureTarget::Format)params.format) ? D3D11_BIND_DEPTH_STENCIL : 0;
            desc.CPUAccessFlags = (params.flags & TextureTarget::cFlag_CpuReadAccess) ? D3D11_CPU_ACCESS_READ : 0;
            desc.MiscFlags = 0;

            HRESULT hr = EngineCore::s_instance.device->CreateTexture3D(&desc, nullptr, (ID3D11Texture3D**) d3dResource.GetAddressOf());
            if (FAILED(hr))
                return nullptr;
        }
        else
        {
            D3D11_TEXTURE2D_DESC desc;
            desc.Width = params.width;
            desc.Height = params.height;
            desc.MipLevels = params.lastMip+1;
            desc.ArraySize = params.arrayLength > 0 ? params.arrayLength : 1;
            desc.Format = TranslateFormat((TextureTarget::Format)params.format);
            desc.SampleDesc.Count = 1 << params.multisampling;
            desc.SampleDesc.Quality = 0;
            desc.Usage = D3D11_USAGE_DEFAULT;
            desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
            desc.BindFlags |= IsDepthFormat((TextureTarget::Format)params.format) ? D3D11_BIND_DEPTH_STENCIL : 0;
            desc.CPUAccessFlags = (params.flags & TextureTarget::cFlag_CpuReadAccess) ? D3D11_CPU_ACCESS_READ : 0;
            desc.MiscFlags = 0;

            HRESULT hr = EngineCore::s_instance.device->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D**) d3dResource.GetAddressOf());
            if (FAILED(hr))
                return nullptr;
        }

        Texture::Details* details = new(g_texturePool.Allocate()) Texture::Details((Texture::Params&)params);
        assert(details != nullptr);
        details->m_d3dResource.Swap(d3dResource);
        return (TextureTarget*)details;
    }

    TextureTargetPtr TextureSystem::Details::CreateTargetWithResource(const TextureTarget::Params& params, ID3D11Resource* d3dResource)
    {
        Texture::Details* details = new(g_texturePool.Allocate()) Texture::Details((Texture::Params&)params);
        assert(details != nullptr);
        details->m_d3dResource.Swap((ComPtr<ID3D11Resource>&)d3dResource);
        return (TextureTarget*) details;
    }

    TargetGroupPtr TextureSystem::CreateTargetGroup(const TargetGroup::Params& params)
    {
        TargetGroup::Details* targetGroup = new(g_targetGroupPool.Allocate()) TargetGroup::Details(params);
        assert(targetGroup != nullptr);
        TargetGroupPtr targetGroupPtr = targetGroup;

        const EngineCore& engine = EngineCore::s_instance;

        if (params.zbuffer != nullptr)
        {
            D3D11_DEPTH_STENCIL_VIEW_DESC desc;
            DescFromTargetParams(desc, params.zbuffer->GetParams(), params.zbufferSlice, params.planes);

            HRESULT hr = engine.device->CreateDepthStencilView(((Texture::Details*)params.zbuffer)->m_d3dResource.Get(), &desc, targetGroup->m_d3dDepthStencilView.GetAddressOf());
            if (FAILED(hr))
                return nullptr;

            desc.Flags = D3D11_DSV_READ_ONLY_DEPTH;
            hr = engine.device->CreateDepthStencilView(((Texture::Details*)params.zbuffer)->m_d3dResource.Get(), &desc, targetGroup->m_d3dReadOnlyDepthStencilView.GetAddressOf());
            if (FAILED(hr))
                return nullptr;
        }
        for (int i = 0; i < TargetGroup::cMaxTargets; i++)
        {
            if (params.targets[i] != nullptr)
            {
                D3D11_RENDER_TARGET_VIEW_DESC desc;
                DescFromTargetParams(desc, params.targets[i]->GetParams(), params.targetSlices[i], params.planes);
                HRESULT hr = engine.device->CreateRenderTargetView(((Texture::Details*)params.targets[i])->m_d3dResource.Get(), &desc, targetGroup->m_d3dTargetViews+i);
                if (FAILED(hr))
                    return nullptr;
            }
        }

        return targetGroup;
    }

    TargetGroup::Details::Details(const TargetGroup::Params& params)
    {
        AssignRef(m_params.zbuffer, params.zbuffer);
        for (m_viewCount = 0; m_viewCount < cMaxTargets && params.targets[m_viewCount] != nullptr; m_viewCount++)
            AssignRef(m_params.targets[m_viewCount], params.targets[m_viewCount]);
    }

    TargetGroup::Details::~Details()
    {
        AssignRef(m_params.zbuffer, nullptr);
        for (unsigned i = 0; i < m_viewCount; i++)
        {
            AssignRef(m_params.targets[i], nullptr);
            m_d3dTargetViews[i]->Release();
        }
    }

    void DestroyRefCounted(Texture* ptr)
    {
        // Defer destruction of textures so engine can ensure that they are all submitted first
        ((Texture::Details*)ptr)->m_next = g_textureGarbage.exchange((Texture::Details*)ptr, std::memory_order_relaxed);
    }

    void DestroyRefCounted(TextureTarget* ptr)
    {
        DestroyRefCounted((Texture*) ptr);
    }

    void DestroyRefCounted(TargetGroup* ptr)
    {
        g_targetGroupPool.Destroy((TargetGroup::Details*)ptr);
    }

    TextureSystem::Details::Details(const char** error)
    {
        new (g_texturePoolPlaceholder.Init()) Pool<Texture::Details>(256);
        new (g_targetGroupPoolPlaceholder.Init()) Pool<TargetGroup::Details>(64);
    }

    TextureSystem::Details::~Details()
    {
        CollectGarbage();
        g_texturePool.~Pool();
        g_targetGroupPool.~Pool();
    }

    void TextureSystem::Details::CollectGarbage()
    {
        Texture::Details* garbage = g_textureGarbage.exchange(nullptr, std::memory_order_relaxed);

        while (garbage != nullptr)
        {
            Texture::Details* next = garbage->m_next;
            g_texturePool.Destroy(garbage);
            garbage = next;
        }
    }

}
示例#6
0
 TextureSystem::Details::Details(const char** error)
 {
     new (g_texturePoolPlaceholder.Init()) Pool<Texture::Details>(256);
     new (g_targetGroupPoolPlaceholder.Init()) Pool<TargetGroup::Details>(64);
 }