D3D11TimerQuery::D3D11TimerQuery() :mFinalized(false), mContext(nullptr), mBeginQuery(nullptr), mEndQuery(nullptr), mDisjointQuery(nullptr), mTimeDelta(0.0f), mQueryEndCalled(false) { D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); D3D11_QUERY_DESC queryDesc; queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; queryDesc.MiscFlags = 0; HRESULT hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mDisjointQuery); if(hr != S_OK) { BS_EXCEPT(RenderingAPIException, "Failed to create a timer query."); } queryDesc.Query = D3D11_QUERY_TIMESTAMP; hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mBeginQuery); if(hr != S_OK) { BS_EXCEPT(RenderingAPIException, "Failed to create a timer query."); } hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mEndQuery); if(hr != S_OK) { BS_EXCEPT(RenderingAPIException, "Failed to create a timer query."); } mContext = device.getImmediateContext(); BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Query); }
void D3D11BlendState::createInternal() { D3D11_BLEND_DESC blendStateDesc; ZeroMemory(&blendStateDesc, sizeof(D3D11_BLEND_DESC)); blendStateDesc.AlphaToCoverageEnable = mProperties.getAlphaToCoverageEnabled(); blendStateDesc.IndependentBlendEnable = mProperties.getIndependantBlendEnable(); for(UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++) { blendStateDesc.RenderTarget[i].BlendEnable = mProperties.getBlendEnabled(i); blendStateDesc.RenderTarget[i].BlendOp = D3D11Mappings::get(mProperties.getBlendOperation(i)); blendStateDesc.RenderTarget[i].BlendOpAlpha = D3D11Mappings::get(mProperties.getAlphaBlendOperation(i)); blendStateDesc.RenderTarget[i].DestBlend = D3D11Mappings::get(mProperties.getDstBlend(i)); blendStateDesc.RenderTarget[i].DestBlendAlpha = D3D11Mappings::get(mProperties.getAlphaDstBlend(i)); blendStateDesc.RenderTarget[i].RenderTargetWriteMask = 0xf & (mProperties.getRenderTargetWriteMask(i)); // Mask out all but last 4 bits blendStateDesc.RenderTarget[i].SrcBlend = D3D11Mappings::get(mProperties.getSrcBlend(i)); blendStateDesc.RenderTarget[i].SrcBlendAlpha = D3D11Mappings::get(mProperties.getAlphaSrcBlend(i)); } D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPI::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); HRESULT hr = device.getD3D11Device()->CreateBlendState(&blendStateDesc, &mBlendState); if(FAILED(hr) || device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "Cannot create blend state.\nError Description:" + errorDescription); } BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_BlendState); BlendState::createInternal(); }
void* D3D11TextureCore::map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch) { D3D11_MAPPED_SUBRESOURCE pMappedResource; pMappedResource.pData = nullptr; mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps()); face = Math::clamp(face, (UINT32)0, mProperties.getNumFaces() - 1); if (mProperties.getTextureType() == TEX_TYPE_3D) face = 0; D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps() + 1); device.getImmediateContext()->Map(res, mLockedSubresourceIdx, flags, 0, &pMappedResource); if (device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription); } UINT32 bytesPerPixel = PixelUtil::getNumElemBytes(mProperties.getFormat()); rowPitch = pMappedResource.RowPitch / bytesPerPixel; slicePitch = pMappedResource.DepthPitch / bytesPerPixel; return pMappedResource.pData; }
void D3D11TextureCore::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target) { D3D11TextureCore* other = static_cast<D3D11TextureCore*>(target.get()); UINT32 srcResIdx = D3D11CalcSubresource(srcMipLevel, srcFace, mProperties.getNumMipmaps() + 1); UINT32 destResIdx = D3D11CalcSubresource(destMipLevel, destFace, target->getProperties().getNumMipmaps() + 1); D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); bool srcHasMultisample = mProperties.getMultisampleCount() > 1; bool destHasMultisample = target->getProperties().getMultisampleCount() > 1; if (srcHasMultisample && destHasMultisample && mProperties.getMultisampleCount() != target->getProperties().getMultisampleCount()) // Resolving from MS to non-MS texture { device.getImmediateContext()->ResolveSubresource(other->getDX11Resource(), destResIdx, mTex, srcResIdx, mDXGIFormat); } else { device.getImmediateContext()->CopySubresourceRegion(other->getDX11Resource(), destResIdx, 0, 0, 0, mTex, srcResIdx, nullptr); if (device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "D3D11 device cannot copy subresource\nError Description:" + errorDescription); } } }
void D3D11TextureCore::unmap(ID3D11Resource* res) { D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); device.getImmediateContext()->Unmap(res, mLockedSubresourceIdx); if (device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "D3D11 device unmap resource\nError Description:" + errorDescription); } }
void* D3D11TextureCore::mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch) { // Note: I am creating and destroying a staging resource every time a texture is read. // Consider offering a flag on init that will keep this active all the time (at the cost of double memory). // Reading is slow operation anyway so I don't believe doing it as we are now will influence it much. if(!mStagingBuffer) createStagingBuffer(); D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); device.getImmediateContext()->CopyResource(mStagingBuffer, mTex); return map(mStagingBuffer, flags, face, mipLevel, rowPitch, slicePitch); }
void D3D11TextureCore::createStagingBuffer() { D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); switch (mProperties.getTextureType()) { case TEX_TYPE_1D: { D3D11_TEXTURE1D_DESC desc; m1DTex->GetDesc(&desc); desc.BindFlags = 0; desc.MiscFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; desc.Usage = D3D11_USAGE_STAGING; device.getD3D11Device()->CreateTexture1D(&desc, nullptr, (ID3D11Texture1D**)(&mStagingBuffer)); } break; case TEX_TYPE_2D: case TEX_TYPE_CUBE_MAP: { D3D11_TEXTURE2D_DESC desc; m2DTex->GetDesc(&desc); desc.BindFlags = 0; desc.MiscFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; desc.Usage = D3D11_USAGE_STAGING; device.getD3D11Device()->CreateTexture2D(&desc, nullptr, (ID3D11Texture2D**)(&mStagingBuffer)); } break; case TEX_TYPE_3D: { D3D11_TEXTURE3D_DESC desc; m3DTex->GetDesc(&desc); desc.BindFlags = 0; desc.MiscFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; desc.Usage = D3D11_USAGE_STAGING; device.getD3D11Device()->CreateTexture3D(&desc, nullptr, (ID3D11Texture3D**)(&mStagingBuffer)); } break; } }
D3D11OcclusionQuery::D3D11OcclusionQuery(bool binary) :OcclusionQuery(binary), mContext(nullptr), mQuery(nullptr), mNumSamples(0), mFinalized(false), mQueryEndCalled(false) { D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); D3D11_QUERY_DESC queryDesc; queryDesc.Query = mBinary ? D3D11_QUERY_OCCLUSION_PREDICATE : D3D11_QUERY_OCCLUSION; queryDesc.MiscFlags = 0; HRESULT hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mQuery); if (hr != S_OK) BS_EXCEPT(RenderingAPIException, "Failed to create an occlusion query."); mContext = device.getImmediateContext(); BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Query); }
void D3D11TextureCore::unmapstaticbuffer() { UINT32 rowWidth = D3D11Mappings::getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth()); UINT32 sliceWidth = D3D11Mappings::getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth(), mStaticBuffer->getHeight()); D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); device.getImmediateContext()->UpdateSubresource(mTex, mLockedSubresourceIdx, nullptr, mStaticBuffer->getData(), rowWidth, sliceWidth); if (device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription); } if(mStaticBuffer != nullptr) bs_delete(mStaticBuffer); }
void D3D11TextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer) { PixelFormat format = mProperties.getFormat(); if (mProperties.getMultisampleCount() > 1) BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly."); mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps()); face = Math::clamp(face, (UINT32)0, mProperties.getNumFaces() - 1); if (face > 0 && mProperties.getTextureType() == TEX_TYPE_3D) BS_EXCEPT(InvalidStateException, "3D texture arrays are not supported."); if ((mProperties.getUsage() & TU_DYNAMIC) != 0) { PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face); PixelUtil::bulkPixelConversion(src, myData); unlock(); } else if ((mProperties.getUsage() & TU_DEPTHSTENCIL) == 0) { D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); UINT subresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps() + 1); UINT32 rowWidth = D3D11Mappings::getSizeInBytes(format, src.getWidth()); UINT32 sliceWidth = D3D11Mappings::getSizeInBytes(format, src.getWidth(), src.getHeight()); device.getImmediateContext()->UpdateSubresource(mTex, subresourceIdx, nullptr, src.getData(), rowWidth, sliceWidth); if (device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription); } BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_Texture); } else { BS_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mProperties.getUsage())); } }
D3D11EventQuery::D3D11EventQuery(UINT32 deviceIdx) :mQuery(nullptr) { assert(deviceIdx == 0 && "Multiple GPUs not supported natively on DirectX 11."); D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPI::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); D3D11_QUERY_DESC queryDesc; queryDesc.Query = D3D11_QUERY_EVENT; queryDesc.MiscFlags = 0; HRESULT hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mQuery); if(hr != S_OK) { BS_EXCEPT(RenderingAPIException, "Failed to create an Event query."); } mContext = device.getImmediateContext(); BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Query); }
void D3D11SamplerStateCore::createInternal() { D3D11_SAMPLER_DESC samplerState; ZeroMemory(&samplerState, sizeof(D3D11_SAMPLER_DESC)); samplerState.AddressU = D3D11Mappings::get(mProperties.getTextureAddressingMode().u); samplerState.AddressV = D3D11Mappings::get(mProperties.getTextureAddressingMode().v); samplerState.AddressW = D3D11Mappings::get(mProperties.getTextureAddressingMode().w); samplerState.BorderColor[0] = mProperties.getBorderColor()[0]; samplerState.BorderColor[1] = mProperties.getBorderColor()[1]; samplerState.BorderColor[2] = mProperties.getBorderColor()[2]; samplerState.BorderColor[3] = mProperties.getBorderColor()[3]; samplerState.ComparisonFunc = D3D11Mappings::get(mProperties.getComparisonFunction()); samplerState.MaxAnisotropy = mProperties.getTextureAnisotropy(); samplerState.MaxLOD = mProperties.getMaximumMip(); samplerState.MinLOD = mProperties.getMinimumMip(); samplerState.MipLODBias = mProperties.getTextureMipmapBias(); bool isComparison = ((mProperties.getTextureFiltering(FT_MIN) & FO_USE_COMPARISON) & (mProperties.getTextureFiltering(FT_MAG) & FO_USE_COMPARISON) & (mProperties.getTextureFiltering(FT_MIP) & FO_USE_COMPARISON)) != 0; FilterOptions minFilter = (FilterOptions)(mProperties.getTextureFiltering(FT_MIN) & ~FO_USE_COMPARISON); FilterOptions magFilter = (FilterOptions)(mProperties.getTextureFiltering(FT_MAG) & ~FO_USE_COMPARISON); FilterOptions mipFilter = (FilterOptions)(mProperties.getTextureFiltering(FT_MIP) & ~FO_USE_COMPARISON); if (minFilter == FO_ANISOTROPIC && magFilter == FO_ANISOTROPIC && mipFilter == FO_ANISOTROPIC) { samplerState.Filter = D3D11_FILTER_ANISOTROPIC; } else { if(minFilter == FO_POINT || minFilter == FO_NONE) { if(magFilter == FO_POINT || magFilter == FO_NONE) { if(mipFilter == FO_POINT || mipFilter == FO_NONE) samplerState.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; else if(mipFilter == FO_LINEAR) samplerState.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; } else if(magFilter == FO_LINEAR) { if(mipFilter == FO_POINT || mipFilter == FO_NONE) samplerState.Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; else if(mipFilter == FO_LINEAR) samplerState.Filter = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; } } else if(minFilter == FO_LINEAR) { if(magFilter == FO_POINT || magFilter == FO_NONE) { if(mipFilter == FO_POINT || mipFilter == FO_NONE) samplerState.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; else if(mipFilter == FO_LINEAR) samplerState.Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; } else if(magFilter == FO_LINEAR) { if(mipFilter == FO_POINT || mipFilter == FO_NONE) samplerState.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; else if(mipFilter == FO_LINEAR) samplerState.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; } } } if(isComparison) { // Adds COMPARISON flag to the filter // See: http://msdn.microsoft.com/en-us/library/windows/desktop/ff476132(v=vs.85).aspx samplerState.Filter = (D3D11_FILTER)(0x80 | samplerState.Filter); } D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); HRESULT hr = device.getD3D11Device()->CreateSamplerState(&samplerState, &mSamplerState); if(FAILED(hr) || device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "Cannot create sampler state.\nError Description:" + errorDescription); } BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_SamplerState); SamplerStateCore::createInternal(); }
void D3D11TextureCore::create3DTex() { UINT32 width = mProperties.getWidth(); UINT32 height = mProperties.getHeight(); UINT32 depth = mProperties.getDepth(); int usage = mProperties.getUsage(); UINT32 numMips = mProperties.getNumMipmaps(); PixelFormat format = mProperties.getFormat(); bool hwGamma = mProperties.isHardwareGammaEnabled(); PixelFormat closestFormat = D3D11Mappings::getClosestSupportedPF(format, hwGamma); // TODO - Consider making this a parameter eventually bool readableDepth = true; // We must have those defined here assert(width > 0 && height > 0 && depth > 0); // Determine which D3D11 pixel format we'll use HRESULT hr; DXGI_FORMAT d3dPF = D3D11Mappings::getPF(closestFormat, hwGamma); if (format != D3D11Mappings::getPF(d3dPF)) { BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format)); } mDXGIColorFormat = d3dPF; mDXGIDepthStencilFormat = d3dPF; D3D11_TEXTURE3D_DESC desc; desc.Width = static_cast<UINT32>(width); desc.Height = static_cast<UINT32>(height); desc.Depth = static_cast<UINT32>(depth); desc.Format = d3dPF; desc.MiscFlags = 0; if ((mProperties.getUsage() & TU_RENDERTARGET) != 0) { desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MipLevels = 1; } else if ((mProperties.getUsage() & TU_DEPTHSTENCIL) != 0) { desc.Usage = D3D11_USAGE_DEFAULT; desc.CPUAccessFlags = 0; desc.MipLevels = 1; if (readableDepth) desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; else desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; mDXGIColorFormat = D3D11Mappings::getShaderResourceDepthStencilPF(closestFormat); mDXGIDepthStencilFormat = d3dPF; } else { desc.Usage = D3D11Mappings::getUsage((GpuBufferUsage)usage); desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage); // Determine total number of mipmaps including main one (d3d11 convention) desc.MipLevels = (numMips == MIP_UNLIMITED || (1U << numMips) > std::max(std::max(width, height), depth)) ? 0 : numMips + 1; } if ((usage & TU_LOADSTORE) != 0) desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; // Create the texture D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); hr = device.getD3D11Device()->CreateTexture3D(&desc, nullptr, &m3DTex); // Check result and except if failed if (FAILED(hr) || device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription); } hr = m3DTex->QueryInterface(__uuidof(ID3D11Resource), (void **)&mTex); if(FAILED(hr) || device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription); } // Create texture view m3DTex->GetDesc(&desc); if (mProperties.getNumMipmaps() != (desc.MipLevels - 1)) { BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \ "Requested: " + toString(mProperties.getNumMipmaps()) + ". Got: " + toString(desc.MipLevels - 1) + "."); } mDXGIFormat = desc.Format; if ((usage & TU_DEPTHSTENCIL) == 0 || readableDepth) { TEXTURE_VIEW_DESC viewDesc; viewDesc.mostDetailMip = 0; viewDesc.numMips = desc.MipLevels; viewDesc.firstArraySlice = 0; viewDesc.numArraySlices = 1; viewDesc.usage = GVU_DEFAULT; SPtr<TextureCore> thisPtr = std::static_pointer_cast<TextureCore>(getThisPtr()); mShaderResourceView = bs_shared_ptr<D3D11TextureView>(new (bs_alloc<D3D11TextureView>()) D3D11TextureView(thisPtr, viewDesc)); } }
void D3D11TextureCore::create2DTex() { UINT32 width = mProperties.getWidth(); UINT32 height = mProperties.getHeight(); int usage = mProperties.getUsage(); UINT32 numMips = mProperties.getNumMipmaps(); PixelFormat format = mProperties.getFormat(); bool hwGamma = mProperties.isHardwareGammaEnabled(); UINT32 sampleCount = mProperties.getMultisampleCount(); TextureType texType = mProperties.getTextureType(); PixelFormat closestFormat = D3D11Mappings::getClosestSupportedPF(format, hwGamma); UINT32 numFaces = mProperties.getNumFaces(); // TODO - Consider making this a parameter eventually bool readableDepth = true; // We must have those defined here assert(width > 0 || height > 0); // Determine which D3D11 pixel format we'll use HRESULT hr; DXGI_FORMAT d3dPF = D3D11Mappings::getPF(closestFormat, hwGamma); if (format != D3D11Mappings::getPF(d3dPF)) { BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format)); } mDXGIColorFormat = d3dPF; mDXGIDepthStencilFormat = d3dPF; D3D11_TEXTURE2D_DESC desc; desc.Width = static_cast<UINT32>(width); desc.Height = static_cast<UINT32>(height); desc.ArraySize = numFaces == 0 ? 1 : numFaces;; desc.Format = d3dPF; desc.MiscFlags = 0; if((usage & TU_RENDERTARGET) != 0) { desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; // TODO - Add flags to allow RT be created without shader resource flags (might be more optimal) desc.CPUAccessFlags = 0; desc.MipLevels = 1; DXGI_SAMPLE_DESC sampleDesc; D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); rs->determineMultisampleSettings(sampleCount, d3dPF, &sampleDesc); desc.SampleDesc = sampleDesc; if (texType == TEX_TYPE_CUBE_MAP) { BS_EXCEPT(NotImplementedException, "Cube map not yet supported as a render target."); // TODO: Will be once I add proper texture array support } } else if((usage & TU_DEPTHSTENCIL) != 0) { desc.Usage = D3D11_USAGE_DEFAULT; desc.CPUAccessFlags = 0; desc.MipLevels = 1; desc.Format = D3D11Mappings::getTypelessDepthStencilPF(closestFormat); if(readableDepth) desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; else desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; DXGI_SAMPLE_DESC sampleDesc; D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); rs->determineMultisampleSettings(sampleCount, d3dPF, &sampleDesc); desc.SampleDesc = sampleDesc; if (texType == TEX_TYPE_CUBE_MAP) { BS_EXCEPT(NotImplementedException, "Cube map not yet supported as a depth stencil target."); // TODO: Will be once I add proper texture array support } mDXGIColorFormat = D3D11Mappings::getShaderResourceDepthStencilPF(closestFormat); mDXGIDepthStencilFormat = d3dPF; } else { desc.Usage = D3D11Mappings::getUsage((GpuBufferUsage)usage); desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage); // Determine total number of mipmaps including main one (d3d11 convention) desc.MipLevels = (numMips == MIP_UNLIMITED || (1U << numMips) > width) ? 0 : numMips + 1; DXGI_SAMPLE_DESC sampleDesc; sampleDesc.Count = 1; sampleDesc.Quality = 0; desc.SampleDesc = sampleDesc; } if (texType == TEX_TYPE_CUBE_MAP) desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; if ((usage & TU_LOADSTORE) != 0) desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; // Create the texture D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr()); D3D11Device& device = rs->getPrimaryDevice(); hr = device.getD3D11Device()->CreateTexture2D(&desc, nullptr, &m2DTex); // Check result and except if failed if (FAILED(hr) || device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription); } hr = m2DTex->QueryInterface(__uuidof(ID3D11Resource), (void **)&mTex); if(FAILED(hr) || device.hasError()) { String errorDescription = device.getErrorDescription(); BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription); } m2DTex->GetDesc(&desc); if(numMips != (desc.MipLevels - 1)) { BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \ "Requested: " + toString(numMips) + ". Got: " + toString(desc.MipLevels - 1) + "."); } mDXGIFormat = desc.Format; // Create shader texture view if((usage & TU_DEPTHSTENCIL) == 0 || readableDepth) { TEXTURE_VIEW_DESC viewDesc; viewDesc.mostDetailMip = 0; viewDesc.numMips = desc.MipLevels; viewDesc.firstArraySlice = 0; viewDesc.numArraySlices = desc.ArraySize; viewDesc.usage = GVU_DEFAULT; SPtr<TextureCore> thisPtr = std::static_pointer_cast<TextureCore>(getThisPtr()); mShaderResourceView = bs_shared_ptr<D3D11TextureView>(new (bs_alloc<D3D11TextureView>()) D3D11TextureView(thisPtr, viewDesc)); } }