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()); } } } } } } }
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(); } }
// **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; } } } }
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; } } }
TextureSystem::Details::Details(const char** error) { new (g_texturePoolPlaceholder.Init()) Pool<Texture::Details>(256); new (g_targetGroupPoolPlaceholder.Init()) Pool<TargetGroup::Details>(64); }