void RTTITypeBase::addNewField(RTTIField* field)
	{
		if(field == nullptr)
		{
			BS_EXCEPT(InvalidParametersException, 
				"Field argument can't be null.");
		}

		int uniqueId = field->mUniqueId;
		auto foundElementById = std::find_if(mFields.begin(), mFields.end(), [uniqueId](RTTIField* x) { return x->mUniqueId == uniqueId; });

		if(foundElementById != mFields.end())
		{
			BS_EXCEPT(InternalErrorException, 
				"Field with the same ID already exists.");
		}

		String& name = field->mName;
		auto foundElementByName = std::find_if(mFields.begin(), mFields.end(), [&name](RTTIField* x) { return x->mName == name; });

		if(foundElementByName != mFields.end())
		{
			BS_EXCEPT(InternalErrorException, 
				"Field with the same name already exists.");
		}

		mFields.push_back(field);
	}
	void D3D9TimerQuery::createQuery()
	{
		mDevice = D3D9RenderAPI::getActiveD3D9Device();

		HRESULT hr = mDevice->CreateQuery(D3DQUERYTYPE_TIMESTAMPDISJOINT, &mDisjointQuery);
		if (hr != S_OK)
		{
			BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
		}

		hr = mDevice->CreateQuery(D3DQUERYTYPE_TIMESTAMPFREQ, &mFreqQuery);
		if (hr != S_OK)
		{
			BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
		}

		hr = mDevice->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &mBeginQuery);
		if (hr != S_OK)
		{
			BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
		}

		hr = mDevice->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &mEndQuery);
		if (hr != S_OK)
		{
			BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
		}
	}
	void D3D11HardwareBuffer::copyData(HardwareBuffer& srcBuffer, UINT32 srcOffset, 
		UINT32 dstOffset, UINT32 length, bool discardWholeBuffer)
	{
		// If we're copying same-size buffers in their entirety
		if (srcOffset == 0 && dstOffset == 0 &&
			length == mSizeInBytes && mSizeInBytes == srcBuffer.getSizeInBytes())
		{
			mDevice.getImmediateContext()->CopyResource(mD3DBuffer, static_cast<D3D11HardwareBuffer&>(srcBuffer).getD3DBuffer());
			if (mDevice.hasError())
			{
				String errorDescription = mDevice.getErrorDescription();
				BS_EXCEPT(RenderingAPIException, "Cannot copy D3D11 resource\nError Description:" + errorDescription);
			}
		}
		else
		{
			// Copy subregion
			D3D11_BOX srcBox;
			srcBox.left = (UINT)srcOffset;
			srcBox.right = (UINT)srcOffset + length;
			srcBox.top = 0;
			srcBox.bottom = 1;
			srcBox.front = 0;
			srcBox.back = 1;

			mDevice.getImmediateContext()->CopySubresourceRegion(mD3DBuffer, 0, (UINT)dstOffset, 0, 0, 
				static_cast<D3D11HardwareBuffer&>(srcBuffer).getD3DBuffer(), 0, &srcBox);
			if (mDevice.hasError())
			{
				String errorDescription = mDevice.getErrorDescription();
				BS_EXCEPT(RenderingAPIException, "Cannot copy D3D11 subresource region\nError Description:" + errorDescription);
			}
		}
	}
	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* GLIndexBufferCore::lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options)
    {
        GLenum access = 0;
        if(mIsLocked)
        {
            BS_EXCEPT(InternalErrorException, 
                "Invalid attempt to lock an index buffer that has already been locked");
        }

#if BS_PROFILING_ENABLED
		if (options == GBL_READ_ONLY || options == GBL_READ_WRITE)
		{
			BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_IndexBuffer);
		}

		if (options == GBL_READ_WRITE || options == GBL_WRITE_ONLY || options == GBL_WRITE_ONLY_DISCARD || options == GBL_WRITE_ONLY_NO_OVERWRITE)
		{
			BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_IndexBuffer);
		}
#endif

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBufferId);

		if ((options == GBL_WRITE_ONLY) || (options == GBL_WRITE_ONLY_NO_OVERWRITE) || (options == GBL_WRITE_ONLY_DISCARD))
		{
			access = GL_MAP_WRITE_BIT;

			if(options == GBL_WRITE_ONLY_DISCARD)
				access |= GL_MAP_INVALIDATE_BUFFER_BIT;
			else if(options == GBL_WRITE_ONLY_NO_OVERWRITE)
				access |= GL_MAP_UNSYNCHRONIZED_BIT;
		}
		else if (options == GBL_READ_ONLY)
			access = GL_MAP_READ_BIT;
		else
			access = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;

		void* pBuffer = nullptr;
		
		if (length > 0)
		{
			pBuffer = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, offset, length, access);

			if (pBuffer == nullptr)
			{
				BS_EXCEPT(InternalErrorException, "Index Buffer: Out of memory");
			}

			mZeroLocked = false;
		}
		else
			mZeroLocked = true;

		void* retPtr = static_cast<void*>(static_cast<unsigned char*>(pBuffer));

		mIsLocked = true;
		return retPtr;
    }
	void RenderTextureCore::initialize()
	{
		RenderTargetCore::initialize();

		const RENDER_SURFACE_CORE_DESC& colorSurface = mDesc.colorSurface;
		if (colorSurface.texture != nullptr)
		{
			SPtr<TextureCore> texture = colorSurface.texture;

			if (texture->getProperties().getUsage() != TU_RENDERTARGET)
				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with render target usage.");

			mColorSurface = TextureCore::requestView(texture, colorSurface.mipLevel, 1,
				colorSurface.face, colorSurface.numFaces, GVU_RENDERTARGET);
		}

		const RENDER_SURFACE_CORE_DESC& depthStencilSurface = mDesc.depthStencilSurface;
		if (depthStencilSurface.texture != nullptr)
		{
			SPtr<TextureCore> texture = depthStencilSurface.texture;

			if (texture->getProperties().getUsage() != TU_DEPTHSTENCIL)
				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with depth stencil usage.");

			mDepthStencilSurface = TextureCore::requestView(texture, depthStencilSurface.mipLevel, 1,
				depthStencilSurface.face, 0, GVU_DEPTHSTENCIL);
		}

		throwIfBuffersDontMatch();

		if (mColorSurface != nullptr)
		{
			assert(mColorSurface->getTexture() != nullptr);

			SPtr<TextureCore> colorTexture = mColorSurface->getTexture();
			const TextureProperties& texProps = colorTexture->getProperties();

			UINT32 numSlices;
			if (texProps.getTextureType() == TEX_TYPE_3D)
				numSlices = texProps.getDepth();
			else
				numSlices = texProps.getNumFaces();

			if ((mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) > numSlices)
			{
				BS_EXCEPT(InvalidParametersException, "Provided number of faces is out of range. Face: " +
					toString(mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) +
					". Max num faces: " + toString(numSlices));
			}

			if (mColorSurface->getMostDetailedMip() > texProps.getNumMipmaps())
			{
				BS_EXCEPT(InvalidParametersException, "Provided number of mip maps is out of range. Mip level: " +
					toString(mColorSurface->getMostDetailedMip()) + ". Max num mipmaps: " + toString(texProps.getNumMipmaps()));
			}
		}
	}
	void D3D11RenderAPI::bindGpuProgram(const SPtr<GpuProgramCore>& prg)
	{
		THROW_IF_NOT_CORE_THREAD;

		switch(prg->getProperties().getType())
		{
		case GPT_VERTEX_PROGRAM:
			{
				D3D11GpuVertexProgramCore* d3d11GpuProgram = static_cast<D3D11GpuVertexProgramCore*>(prg.get());
				mDevice->getImmediateContext()->VSSetShader(d3d11GpuProgram->getVertexShader(), nullptr, 0);
				mActiveVertexShader = std::static_pointer_cast<D3D11GpuProgramCore>(prg);
				break;
			}
		case GPT_FRAGMENT_PROGRAM:
			{
				D3D11GpuFragmentProgramCore* d3d11GpuProgram = static_cast<D3D11GpuFragmentProgramCore*>(prg.get());
				mDevice->getImmediateContext()->PSSetShader(d3d11GpuProgram->getPixelShader(), nullptr, 0);
				break;
			}
		case GPT_GEOMETRY_PROGRAM:
			{
				D3D11GpuGeometryProgramCore* d3d11GpuProgram = static_cast<D3D11GpuGeometryProgramCore*>(prg.get());
				mDevice->getImmediateContext()->GSSetShader(d3d11GpuProgram->getGeometryShader(), nullptr, 0);
				break;
			}
		case GPT_DOMAIN_PROGRAM:
			{
				D3D11GpuDomainProgramCore* d3d11GpuProgram = static_cast<D3D11GpuDomainProgramCore*>(prg.get());
				mDevice->getImmediateContext()->DSSetShader(d3d11GpuProgram->getDomainShader(), nullptr, 0);
				break;
			}
		case GPT_HULL_PROGRAM:
			{
				D3D11GpuHullProgramCore* d3d11GpuProgram = static_cast<D3D11GpuHullProgramCore*>(prg.get());
				mDevice->getImmediateContext()->HSSetShader(d3d11GpuProgram->getHullShader(), nullptr, 0);
				break;
			}
		case GPT_COMPUTE_PROGRAM:
			{
				D3D11GpuComputeProgramCore* d3d11GpuProgram = static_cast<D3D11GpuComputeProgramCore*>(prg.get());
				mDevice->getImmediateContext()->CSSetShader(d3d11GpuProgram->getComputeShader(), nullptr, 0);
				break;
			}
		default:
			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(prg->getProperties().getType()));
		}

		if (mDevice->hasError())
			BS_EXCEPT(RenderingAPIException, "Failed to bindGpuProgram : " + mDevice->getErrorDescription());

		BS_INC_RENDER_STAT(NumGpuProgramBinds);
	}
	void GLTextureBuffer::blitFromTexture(GLTextureBuffer* src, const PixelVolume& srcBox, const PixelVolume& dstBox)
	{
		if (src->mMultisampleCount > 0 && mMultisampleCount == 0) // Resolving MS texture
		{
			if (mTarget != GL_TEXTURE_2D || mTarget != GL_TEXTURE_2D_MULTISAMPLE)
				BS_EXCEPT(InvalidParametersException, "Non-2D multisampled texture not supported.");

			GLint currentFBO = 0;
			glGetIntegerv(GL_FRAMEBUFFER_BINDING, &currentFBO);

			GLuint readFBO = GLRTTManager::instance().getBlitReadFBO();
			GLuint drawFBO = GLRTTManager::instance().getBlitDrawFBO();

			// Attach source texture
			glBindFramebuffer(GL_FRAMEBUFFER, readFBO);
			src->bindToFramebuffer(0, 0, true);

			// Attach destination texture
			glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
			bindToFramebuffer(0, 0, true);

			// Perform blit
			glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);

			glReadBuffer(GL_COLOR_ATTACHMENT0);
			glDrawBuffer(GL_COLOR_ATTACHMENT0);

			glBlitFramebuffer(srcBox.left, srcBox.top, srcBox.right, srcBox.bottom, 
				dstBox.left, dstBox.top, dstBox.right, dstBox.bottom, GL_COLOR_BUFFER_BIT, GL_NEAREST);

			// Restore the previously bound FBO
			glBindFramebuffer(GL_FRAMEBUFFER, currentFBO);
		}
		else // Just plain copy
		{
			if (mMultisampleCount != src->mMultisampleCount)
				BS_EXCEPT(InvalidParametersException, "When copying textures their multisample counts must match.");

			if (mTarget == GL_TEXTURE_3D) // 3D textures can't have arrays so their Z coordinate is handled differently
			{
				glCopyImageSubData(src->mTextureID, src->mTarget, src->mLevel, srcBox.left, srcBox.top, srcBox.front,
					mTextureID, mTarget, mLevel, dstBox.left, dstBox.top, dstBox.front, srcBox.getWidth(), srcBox.getHeight(), srcBox.getDepth());
			}
			else
			{
				glCopyImageSubData(src->mTextureID, src->mTarget, src->mLevel, srcBox.left, srcBox.top, src->mFace,
					mTextureID, mTarget, mLevel, dstBox.left, dstBox.top, mFace, srcBox.getWidth(), srcBox.getHeight(), 1);
			}
		}		
	}
Exemple #9
0
	void RTTIField::checkIsArray(bool array)
	{
		if(array && !mIsVectorType)
		{
			BS_EXCEPT(InternalErrorException, 
				"Invalid field type. Needed an array type but got a single type.");
		}

		if(!array && mIsVectorType)
		{
			BS_EXCEPT(InternalErrorException, 
				"Invalid field type. Needed a single type but got an array type.");
		}
	}
	void D3D11RenderAPI::setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers)
	{
		THROW_IF_NOT_CORE_THREAD;

		UINT32 maxBoundVertexBuffers = mCurrentCapabilities->getMaxBoundVertexBuffers();
		if(index < 0 || (index + numBuffers) >= maxBoundVertexBuffers)
			BS_EXCEPT(InvalidParametersException, "Invalid vertex index: " + toString(index) + ". Valid range is 0 .. " + toString(maxBoundVertexBuffers - 1));

		ID3D11Buffer* dx11buffers[MAX_BOUND_VERTEX_BUFFERS];
		UINT32 strides[MAX_BOUND_VERTEX_BUFFERS];
		UINT32 offsets[MAX_BOUND_VERTEX_BUFFERS];

		for(UINT32 i = 0; i < numBuffers; i++)
		{
			SPtr<D3D11VertexBufferCore> vertexBuffer = std::static_pointer_cast<D3D11VertexBufferCore>(buffers[i]);
			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();

			dx11buffers[i] = vertexBuffer->getD3DVertexBuffer();

			strides[i] = vbProps.getVertexSize();
			offsets[i] = 0;
		}

		mDevice->getImmediateContext()->IASetVertexBuffers(index, numBuffers, dx11buffers, strides, offsets);

		BS_INC_RENDER_STAT(NumVertexBufferBinds);
	}
Exemple #11
0
	T TGpuDataParam<T, Core>::get(UINT32 arrayIdx) const
	{
		if (mParent == nullptr)
			return T();

		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSet, mParamDesc->paramBlockSlot);
		if (paramBlock == nullptr)
			return T();

#if BS_DEBUG_MODE
		if (arrayIdx >= mParamDesc->arraySize)
		{
			BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
				toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
		}
#endif

		UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);
		UINT32 sizeBytes = std::min(elementSizeBytes, (UINT32)sizeof(T));

		T value;
		paramBlock->read((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), &value, sizeBytes);

		return value;
	}
Exemple #12
0
	void TGpuParamStruct<Core>::get(void* value, UINT32 sizeBytes, UINT32 arrayIdx) const
	{
		if (mParent == nullptr)
			return;

		GpuParamBufferType paramBlock = mParent->getParamBlockBuffer(mParamDesc->paramBlockSet, mParamDesc->paramBlockSlot);
		if (paramBlock == nullptr)
			return;

		UINT32 elementSizeBytes = mParamDesc->elementSize * sizeof(UINT32);

#if BS_DEBUG_MODE
		if (sizeBytes > elementSizeBytes)
		{
			LOGWRN("Provided element size larger than maximum element size. Maximum size: " +
				toString(elementSizeBytes) + ". Supplied size: " + toString(sizeBytes));
		}

		if (arrayIdx >= mParamDesc->arraySize)
		{
			BS_EXCEPT(InvalidParametersException, "Array index out of range. Array size: " +
				toString(mParamDesc->arraySize) + ". Requested size: " + toString(arrayIdx));
		}
#endif
		sizeBytes = std::min(elementSizeBytes, sizeBytes);

		paramBlock->read((mParamDesc->cpuMemOffset + arrayIdx * mParamDesc->arrayElementStride) * sizeof(UINT32), value, sizeBytes);
	}
	ScriptObjectBase::~ScriptObjectBase() 
	{
		if(mManagedInstance != nullptr)
			BS_EXCEPT(InvalidStateException, "Script object is being destroyed without its instance previously being released.");

		ScriptObjectManager::instance().unregisterScriptObject(this);
	}
	void RenderTextureCore::throwIfBuffersDontMatch() const
	{
		if (mColorSurface == nullptr || mDepthStencilSurface == nullptr)
			return;

		const TextureProperties& colorProps = mColorSurface->getTexture()->getProperties();
		const TextureProperties& depthProps = mDepthStencilSurface->getTexture()->getProperties();

		UINT32 colorMsCount = colorProps.getMultisampleCount();
		UINT32 depthMsCount = depthProps.getMultisampleCount();

		if (colorMsCount == 0)
			colorMsCount = 1;

		if (depthMsCount == 0)
			depthMsCount = 1;

		if (colorProps.getWidth() != depthProps.getWidth() ||
			colorProps.getHeight() != depthProps.getHeight() ||
			colorMsCount != depthMsCount)
		{
			String errorInfo = "\nWidth: " + toString(colorProps.getWidth()) + "/" + toString(depthProps.getWidth());
			errorInfo += "\nHeight: " + toString(colorProps.getHeight()) + "/" + toString(depthProps.getHeight());
			errorInfo += "\nMultisample Count: " + toString(colorMsCount) + "/" + toString(depthMsCount);

			BS_EXCEPT(InvalidParametersException, "Provided texture and depth stencil buffer don't match!" + errorInfo);
		}
	}
	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 D3D11RenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil)
	{
		THROW_IF_NOT_CORE_THREAD;

		mActiveRenderTarget = target;

		UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
		ID3D11RenderTargetView** views = bs_newN<ID3D11RenderTargetView*>(maxRenderTargets);
		memset(views, 0, sizeof(ID3D11RenderTargetView*) * maxRenderTargets);

		ID3D11DepthStencilView* depthStencilView = nullptr;

		if (target != nullptr)
		{
			target->getCustomAttribute("RTV", views);

			if(readOnlyDepthStencil)
				target->getCustomAttribute("RODSV", &depthStencilView);
			else
				target->getCustomAttribute("DSV", &depthStencilView);
		}

		// Bind render targets
		mDevice->getImmediateContext()->OMSetRenderTargets(maxRenderTargets, views, depthStencilView);
		if (mDevice->hasError())
			BS_EXCEPT(RenderingAPIException, "Failed to setRenderTarget : " + mDevice->getErrorDescription());

		bs_deleteN(views, maxRenderTargets);
		applyViewport();

		BS_INC_RENDER_STAT(NumRenderTargetChanges);
	}
	void D3D11RenderAPI::unbindGpuProgram(GpuProgramType gptype)
	{
		THROW_IF_NOT_CORE_THREAD;

		switch(gptype)
		{
		case GPT_VERTEX_PROGRAM:
			mDevice->getImmediateContext()->VSSetShader(nullptr, nullptr, 0);
			mActiveVertexShader = nullptr;
			break;
		case GPT_FRAGMENT_PROGRAM:
			mDevice->getImmediateContext()->PSSetShader(nullptr, nullptr, 0);
			break;
		case GPT_GEOMETRY_PROGRAM:
			mDevice->getImmediateContext()->GSSetShader(nullptr, nullptr, 0);
			break;
		case GPT_DOMAIN_PROGRAM:
			mDevice->getImmediateContext()->DSSetShader(nullptr, nullptr, 0);
			break;
		case GPT_HULL_PROGRAM:
			mDevice->getImmediateContext()->HSSetShader(nullptr, nullptr, 0);
			break;
		case GPT_COMPUTE_PROGRAM:
			mDevice->getImmediateContext()->CSSetShader(nullptr, nullptr, 0);
			break;
		default:
			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
		}

		BS_INC_RENDER_STAT(NumGpuProgramBinds);
	}
Exemple #20
0
	void throwIfCoreThread()
	{
#if !BS_FORCE_SINGLETHREADED_RENDERING
		if(BS_THREAD_CURRENT_ID == CoreThread::instance().getCoreThreadId())
			BS_EXCEPT(InternalErrorException, "This method cannot be accessed from the core thread.");
#endif
	}
	MonoClass* MonoAssembly::getClass(const String& ns, const String& typeName, ::MonoClass* rawMonoClass) const
	{
		if (!mIsLoaded)
			BS_EXCEPT(InvalidStateException, "Trying to use an unloaded assembly.");

		if (rawMonoClass == nullptr)
			return nullptr;

		auto iterFind = mClassesByRaw.find(rawMonoClass);

		if (iterFind != mClassesByRaw.end())
			return iterFind->second;

		MonoClass* newClass = new (bs_alloc<MonoClass>()) MonoClass(ns, typeName, rawMonoClass, this);

		mClassesByRaw[rawMonoClass] = newClass;

		if (!isGenericClass(typeName)) // No point in referencing generic types by name as all instances share it
		{
			MonoAssembly::ClassId classId(ns, typeName);
			mClasses[classId] = newClass;
		}

		return newClass;
	}
Exemple #22
0
	SPtr<typename TTechnique<Core>::PassType> TTechnique<Core>::getPass(UINT32 idx) const
	{
		if (idx < 0 || idx >= (UINT32)mPasses.size())
			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));

		return mPasses[idx];
	}
	VertexElementSemantic D3D9Mappings::get(D3DDECLUSAGE sem)
	{
		switch (sem)
		{
		case D3DDECLUSAGE_BLENDINDICES:
			return VES_BLEND_INDICES;
		case D3DDECLUSAGE_BLENDWEIGHT:
			return VES_BLEND_WEIGHTS;
		case D3DDECLUSAGE_COLOR:
			return VES_COLOR;
		case D3DDECLUSAGE_NORMAL:
			return VES_NORMAL;
		case D3DDECLUSAGE_POSITION:
			return VES_POSITION;
		case D3DDECLUSAGE_TEXCOORD:
			return VES_TEXCOORD;
		case D3DDECLUSAGE_BINORMAL:
			return VES_BITANGENT;
		case D3DDECLUSAGE_TANGENT:
			return VES_TANGENT;
		default:
			BS_EXCEPT(RenderingAPIException, "Invalid semantic for D3D9 render system: " + toString(sem));
		}

		return VES_POSITION;
	}
	void MenuItemManager::reloadAssemblyData()
	{
		clearMenuItems();

		// Reload MenuItem attribute from editor assembly
		MonoAssembly* editorAssembly = MonoManager::instance().getAssembly(EDITOR_ASSEMBLY);
		mMenuItemAttribute = editorAssembly->getClass(EDITOR_NS, "MenuItem");
		if (mMenuItemAttribute == nullptr)
			BS_EXCEPT(InvalidStateException, "Cannot find MenuItem managed class.");

		mPathField = mMenuItemAttribute->getField("path");
		mShortcutField = mMenuItemAttribute->getField("shortcut");
		mPriorityField = mMenuItemAttribute->getField("priority");
		mSeparatorField = mMenuItemAttribute->getField("separator");

		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();

		Vector<String> scriptAssemblyNames = mScriptObjectManager.getScriptAssemblies();
		for (auto& assemblyName : scriptAssemblyNames)
		{
			MonoAssembly* assembly = MonoManager::instance().getAssembly(assemblyName);

			// Find new menu item methods
			const Vector<MonoClass*>& allClasses = assembly->getAllClasses();
			for (auto curClass : allClasses)
			{
				const Vector<MonoMethod*>& methods = curClass->getAllMethods();
				for (auto& curMethod : methods)
				{
					String path;
					ShortcutKey shortcutKey = ShortcutKey::NONE;
					INT32 priority = 0;
					bool separator = false;
					if (parseMenuItemMethod(curMethod, path, shortcutKey, priority, separator))
					{
						std::function<void()> callback = std::bind(&MenuItemManager::menuItemCallback, curMethod);

						if (separator)
						{
							Vector<String> pathElements = StringUtil::split(path, "/");
							String separatorPath;
							if (pathElements.size() > 1)
							{
								const String& lastElem = pathElements[pathElements.size() - 1];
								separatorPath = path;
								separatorPath.erase(path.size() - lastElem.size() - 1, lastElem.size() + 1);
							}

							GUIMenuItem* separatorItem = mainWindow->getMenuBar().addMenuItemSeparator(separatorPath, priority);
							mMenuItems.push_back(separatorItem);
						}

						GUIMenuItem* menuItem = mainWindow->getMenuBar().addMenuItem(path, callback, priority, shortcutKey);
						mMenuItems.push_back(menuItem);
					}
				}
			}
		}
	}
Exemple #25
0
	ID3D11ShaderResourceView* GpuBufferView::createSRV(D3D11GpuBuffer* buffer, UINT32 firstElement, UINT32 elementWidth, UINT32 numElements)
	{
		const GpuBufferProperties& props = buffer->getProperties();

		if (props.getType() == GBT_APPENDCONSUME)
			BS_EXCEPT(InvalidParametersException, "Cannot create ShaderResourceView for an append/consume buffer.");

		D3D11_SHADER_RESOURCE_VIEW_DESC desc;
		ZeroMemory(&desc, sizeof(desc));

		if (props.getType() == GBT_STRUCTURED || props.getType() == GBT_STANDARD)
		{
			desc.Format = DXGI_FORMAT_UNKNOWN;
			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
			desc.Buffer.FirstElement = firstElement;
			desc.Buffer.NumElements = numElements;
		}
		else if (props.getType() == GBT_RAW)
		{
			desc.Format = DXGI_FORMAT_R32_TYPELESS;
			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
			desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
			desc.BufferEx.FirstElement = firstElement;
			desc.BufferEx.NumElements = numElements;
		}
		else if (props.getType() == GBT_INDIRECTARGUMENT)
		{
			desc.Format = DXGI_FORMAT_R32_UINT;
			desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
			desc.Buffer.ElementOffset = firstElement * elementWidth;
			desc.Buffer.ElementWidth = elementWidth;
		}

		ID3D11ShaderResourceView* srv = nullptr;

		D3D11RenderAPI* d3d11rs = static_cast<D3D11RenderAPI*>(D3D11RenderAPI::instancePtr());
		HRESULT hr = d3d11rs->getPrimaryDevice().getD3D11Device()->CreateShaderResourceView(buffer->getDX11Buffer(), &desc, &srv);

		if (FAILED(hr) || d3d11rs->getPrimaryDevice().hasError())
		{
			String msg = d3d11rs->getPrimaryDevice().getErrorDescription();
			BS_EXCEPT(RenderingAPIException, "Cannot create ShaderResourceView: " + msg);
		}

		return srv;
	}
Exemple #26
0
	CoreObject::~CoreObject() 
	{
		if(!isDestroyed())
		{
			// Object must be released with destroy() otherwise engine can still try to use it, even if it was destructed
			// (e.g. if an object has one of its methods queued in a command queue, and is destructed, you will be accessing invalid memory)
			BS_EXCEPT(InternalErrorException, "Destructor called but object is not destroyed. This will result in nasty issues.");
		}

#if BS_DEBUG_MODE
		if(!mThis.expired())
		{
			BS_EXCEPT(InternalErrorException, "Shared pointer to this object still has active references but " \
				"the object is being deleted? You shouldn't delete CoreObjects manually.");
		}
#endif
	}
	MonoObject* ScriptDropDownWindow::internal_CreateInstance(MonoString* ns, MonoString* typeName, 
		ScriptEditorWindow* parentWindow, Vector2I* position)
	{
		String strTypeName = MonoUtil::monoToString(typeName);
		String strNamespace = MonoUtil::monoToString(ns);
		String fullName = strNamespace + "." + strTypeName;

		MonoClass* windowClass = MonoManager::instance().findClass(strNamespace, strTypeName);
		if (windowClass == nullptr)
			return nullptr;

		MonoAssembly* assembly = MonoManager::instance().getAssembly(EDITOR_ASSEMBLY);

		MonoClass* defaultSizeAttrib = assembly->getClass("BansheeEditor", "DefaultSize");
		if (defaultSizeAttrib == nullptr)
			BS_EXCEPT(InternalErrorException, "Cannot find DefaultSize managed class.");

		MonoField* defaultWidthField = defaultSizeAttrib->getField("width");
		MonoField* defaultHeightField = defaultSizeAttrib->getField("height");

		int width = 200;
		int height = 200;

		MonoObject* defaultSizeObj = windowClass->getAttribute(defaultSizeAttrib);
		if (defaultSizeObj != nullptr)
		{
			defaultWidthField->get(defaultSizeObj, &width);
			defaultHeightField->get(defaultSizeObj, &height);
		}

		MonoObject* instance = windowClass->createInstance(false);

		ManagedDropDownWindow* dropDownWindow = nullptr;
		if (parentWindow != nullptr && !parentWindow->isDestroyed())
		{
			EditorWidgetBase* editorWidget = parentWindow->getEditorWidget();
			EditorWidgetContainer* parentContainer = editorWidget->_getParent();
			if (parentContainer != nullptr)
			{
				SPtr<RenderWindow> parentRenderWindow = parentContainer->getParentWindow()->getRenderWindow();
				SPtr<Camera> parentCamera = parentContainer->getParentWidget().getCamera();

				position->x += editorWidget->getX();
				position->y += editorWidget->getY();

				dropDownWindow = DropDownWindowManager::instance().open<ManagedDropDownWindow>(
					parentRenderWindow, parentCamera, *position, instance, width, height);
			}
		}

		ScriptDropDownWindow* nativeInstance = new (bs_alloc<ScriptDropDownWindow>()) ScriptDropDownWindow(dropDownWindow);

		if (dropDownWindow != nullptr)
			dropDownWindow->initialize(nativeInstance);

		windowClass->construct(instance);
		return instance;
	}
	void ScriptEditorWindow::registerManagedEditorWindows()
	{
		MonoAssembly* assembly = MonoManager::instance().getAssembly(EDITOR_ASSEMBLY);

		if(assembly != nullptr)
		{
			MonoClass* defaultSizeAttrib = assembly->getClass("BansheeEditor", "DefaultSize");
			if (defaultSizeAttrib == nullptr)
				BS_EXCEPT(InternalErrorException, "Cannot find DefaultSize managed attribute.");

			MonoField* defaultWidthField = defaultSizeAttrib->getField("width");
			MonoField* defaultHeightField = defaultSizeAttrib->getField("height");

			MonoClass* undoRedoLocalAttrib = assembly->getClass("BansheeEditor", "UndoRedoLocal");
			if (undoRedoLocalAttrib == nullptr)
				BS_EXCEPT(InternalErrorException, "Cannot find UndoRedoLocal managed attribute.");

			MonoClass* editorWindowClass = assembly->getClass("BansheeEditor", "EditorWindow");

			const Vector<MonoClass*>& allClasses = assembly->getAllClasses();
			for(auto& curClass : allClasses)
			{
				if(curClass->isSubClassOf(editorWindowClass) && curClass != editorWindowClass)
				{
					UINT32 width = 400;
					UINT32 height = 400;

					MonoObject* defaultSize = curClass->getAttribute(defaultSizeAttrib);
					if (defaultSize != nullptr)
					{
						defaultWidthField->get(defaultSize, &width);
						defaultHeightField->get(defaultSize, &height);
					}

					bool hasLocalUndoRedo = curClass->getAttribute(undoRedoLocalAttrib) != nullptr;

					const String& className = curClass->getFullName();
					EditorWidgetManager::instance().registerWidget(className, 
						std::bind(&ScriptEditorWindow::openEditorWidgetCallback, curClass->getNamespace(), 
						curClass->getTypeName(), width, height, hasLocalUndoRedo, _1));
					AvailableWindowTypes.push_back(className);
				}
			}
		}
	}
	void EditorWidgetManager::registerWidget(const String& name, std::function<EditorWidgetBase*(EditorWidgetContainer&)> createCallback)
	{
		auto iterFind = mCreateCallbacks.find(name);

		if(iterFind != mCreateCallbacks.end())
			BS_EXCEPT(InvalidParametersException, "Widget with the same name is already registered. Name: \"" + name + "\"");

		mCreateCallbacks[name] = createCallback;
	}
Exemple #30
0
	void RTTIField::checkIsDataBlock()
	{
		if(!isDataBlockType())
		{
			BS_EXCEPT(InternalErrorException, 
				"Invalid field type. Needed: Data block. Got: " + toString(mIsVectorType) + ", " + 
				toString(isPlainType()) + ", " + toString(isReflectableType()) + ", " + toString(isDataBlockType()) + ", " + toString(isReflectablePtrType()));
		}
	}