コード例 #1
0
void PhysXRigidbody::updateMassDistribution()
{
    if (((UINT32)mFlags & (UINT32)Flag::AutoTensors) == 0)
        return;

    if (((UINT32)mFlags & (UINT32)Flag::AutoMass) == 0)
    {
        PxRigidBodyExt::setMassAndUpdateInertia(*mInternal, mInternal->getMass());
    }
    else
    {
        UINT32 numShapes = mInternal->getNbShapes();
        if (numShapes == 0)
        {
            PxRigidBodyExt::setMassAndUpdateInertia(*mInternal, mInternal->getMass());
            return;
        }

        PxShape** shapes = (PxShape**)bs_stack_alloc(sizeof(PxShape*) * numShapes);
        mInternal->getShapes(shapes, numShapes);

        float* masses = (float*)bs_stack_alloc(sizeof(float) * numShapes);
        for (UINT32 i = 0; i < numShapes; i++)
            masses[i] = ((Collider*)shapes[i]->userData)->getMass();

        PxRigidBodyExt::setMassAndUpdateInertia(*mInternal, masses, numShapes);

        bs_stack_free(masses);
        bs_stack_free(shapes);
    }
}
コード例 #2
0
	VkPipelineLayout VulkanDescriptorManager::getPipelineLayout(VulkanDescriptorLayout** layouts, UINT32 numLayouts)
	{
		VulkanPipelineLayoutKey key(layouts, numLayouts);

		auto iterFind = mPipelineLayouts.find(key);
		if (iterFind != mPipelineLayouts.end())
			return iterFind->second;

		// Create new
		VkDescriptorSetLayout* setLayouts = (VkDescriptorSetLayout*)bs_stack_alloc(sizeof(VkDescriptorSetLayout) * numLayouts);
		for(UINT32 i = 0; i < numLayouts; i++)
			setLayouts[i] = layouts[i]->getHandle();

		VkPipelineLayoutCreateInfo layoutCI;
		layoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
		layoutCI.pNext = nullptr;
		layoutCI.flags = 0;
		layoutCI.pushConstantRangeCount = 0;
		layoutCI.pPushConstantRanges = nullptr;
		layoutCI.setLayoutCount = numLayouts;
		layoutCI.pSetLayouts = setLayouts;

		VkPipelineLayout pipelineLayout;
		VkResult result = vkCreatePipelineLayout(mDevice.getLogical(), &layoutCI, gVulkanAllocator, &pipelineLayout);
		assert(result == VK_SUCCESS);

		bs_stack_free(setLayouts);

		key.layouts = (VulkanDescriptorLayout**)bs_alloc(sizeof(VulkanDescriptorLayout*) * numLayouts);
		memcpy(key.layouts, layouts, sizeof(VulkanDescriptorLayout*) * numLayouts);

		mPipelineLayouts.insert(std::make_pair(key, pipelineLayout));
		return pipelineLayout;
	}
コード例 #3
0
void PhysXRigidbody::setFlags(Flag flags)
{
    bool ccdEnabledOld = mInternal->getRigidBodyFlags() & PxRigidBodyFlag::eENABLE_CCD;
    bool ccdEnabledNew = ((UINT32)flags & (UINT32)Flag::CCD) != 0;

    if(ccdEnabledOld != ccdEnabledNew)
    {
        if(ccdEnabledNew)
        {
            if (!gPhysics().hasFlag(PhysicsFlag::CCD_Enable))
                LOGWRN("Enabling CCD on a Rigidbody but CCD is not enabled globally.");
        }

        mInternal->setRigidBodyFlag(PxRigidBodyFlag::eENABLE_CCD, ccdEnabledNew);

        // Enable/disable CCD on shapes so the filter can handle them properly
        UINT32 numShapes = mInternal->getNbShapes();
        PxShape** shapes = (PxShape**)bs_stack_alloc(sizeof(PxShape*) * numShapes);

        mInternal->getShapes(shapes, sizeof(PxShape*) * numShapes);

        for (UINT32 i = 0; i < numShapes; i++)
        {
            Collider* collider = (Collider*)shapes[i]->userData;
            collider->_getInternal()->_setCCD(ccdEnabledNew);
        }
    }

    Rigidbody::setFlags(flags);
}
コード例 #4
0
ファイル: BsAudioUtility.cpp プロジェクト: R4N3/BansheeEngine
	void AudioUtility::convertBitDepth(const UINT8* input, UINT32 inBitDepth, UINT8* output, UINT32 outBitDepth, UINT32 numSamples)
	{
		INT32* srcBuffer = nullptr;

		bool needTempBuffer = inBitDepth != 32;
		if (needTempBuffer)
			srcBuffer = (INT32*)bs_stack_alloc(numSamples * sizeof(INT32));
		else
			srcBuffer = (INT32*)input;

		// Note: I convert to a temporary 32-bit buffer and then use that to convert to actual requested bit depth. 
		//       It would be more efficient to convert directly from source to requested depth without a temporary buffer,
		//       at the cost of additional complexity. If this method ever becomes a performance issue consider that.
		switch (inBitDepth)
		{
		case 8:
			convert8To32Bits(input, srcBuffer, numSamples);
			break;
		case 16:
			convert16To32Bits((INT16*)input, srcBuffer, numSamples);
			break;
		case 24:
			BansheeEngine::convert24To32Bits(input, srcBuffer, numSamples);
			break;
		case 32:
			// Do nothing
			break;
		default:
			assert(false);
			break;
		}

		switch (outBitDepth)
		{
		case 8:
			convert32To8Bits(srcBuffer, output, numSamples);
			break;
		case 16:
			convert32To16Bits(srcBuffer, (INT16*)output, numSamples);
			break;
		case 24:
			convert32To24Bits(srcBuffer, output, numSamples);
			break;
		case 32:
			memcpy(output, srcBuffer, numSamples * sizeof(INT32));
			break;
		default:
			assert(false);
			break;
		}

		if (needTempBuffer)
		{
			bs_stack_free(srcBuffer);
			srcBuffer = nullptr;
		}
	}
コード例 #5
0
void PhysXRigidbody::removeColliders()
{
    UINT32 numShapes = mInternal->getNbShapes();
    PxShape** shapes = (PxShape**)bs_stack_alloc(sizeof(PxShape*) * numShapes);

    mInternal->getShapes(shapes, sizeof(PxShape*) * numShapes);

    for (UINT32 i = 0; i < numShapes; i++)
    {
        Collider* collider = (Collider*)shapes[i]->userData;
        collider->_getInternal()->_setCCD(false);

        mInternal->detachShape(*shapes[i]);
    }

    bs_stack_free(shapes);
}
コード例 #6
0
ファイル: BsMeshUtility.cpp プロジェクト: lysannschlegel/bsf
	void TriangleClipperBase::getOrderedVertices(const ClipFace& face, UINT32* sortedVerts)
	{
		UINT32 numEdges = (UINT32)face.edges.size();
		UINT32* sortedEdges = (UINT32*)bs_stack_alloc(sizeof(UINT32) * numEdges);
		for (UINT32 i = 0; i < numEdges; i++)
			sortedEdges[i] = face.edges[i];

		// Bubble sort to arrange edges in contiguous order
		for (UINT32 i0 = 0, i1 = 1, choice = 1; i1 < numEdges - 1; i0 = i1, i1++)
		{
			const ClipEdge& edge0 = mesh.edges[sortedEdges[i0]];

			UINT32 current = edge0.verts[choice];
			for (UINT32 j = i1; j < numEdges; j++)
			{
				const ClipEdge& edge1 = mesh.edges[sortedEdges[j]];

				if (edge1.verts[0] == current || edge1.verts[1] == current)
				{
					std::swap(sortedEdges[i1], sortedEdges[j]);
					choice = 1;
					break;
				}
			}
		}

		// Add the first two vertices
		sortedVerts[0] = mesh.edges[sortedEdges[0]].verts[0];
		sortedVerts[1] = mesh.edges[sortedEdges[0]].verts[1];

		// Add the remaining vertices
		for (UINT32 i = 1; i < numEdges; i++)
		{
			const ClipEdge& edge = mesh.edges[sortedEdges[i]];

			if (edge.verts[0] == sortedVerts[i])
				sortedVerts[i + 1] = edge.verts[1];
			else
				sortedVerts[i + 1] = edge.verts[0];
		}

		bs_stack_free(sortedEdges);
	}
コード例 #7
0
ファイル: BsMeshUtility.cpp プロジェクト: lysannschlegel/bsf
	void TriangleClipperBase::getOrderedFaces(FrameVector<FrameVector<UINT32>>& sortedFaces)
	{
		for (UINT32 i = 0; i < (UINT32)mesh.faces.size(); i++)
		{
			const ClipFace& face = mesh.faces[i];

			if (face.visible)
			{
				// Get the ordered vertices of the face. The first and last
				// element of the array are the same since the polyline is
				// closed.
				UINT32 numSortedVerts = (UINT32)face.edges.size() + 1;
				UINT32* sortedVerts = (UINT32*)bs_stack_alloc(sizeof(UINT32) * numSortedVerts);

				getOrderedVertices(face, sortedVerts);

				FrameVector<UINT32> faceVerts;

				// The convention is that the vertices should be counterclockwise
				// ordered when viewed from the negative side of the plane of the
				// face. If you need the opposite convention, switch the
				// inequality in the if-else statement.
				Vector3 normal = getNormal(sortedVerts, numSortedVerts);
				if (Vector3::dot(mesh.faces[i].normal, normal) < 0)
				{
					// Clockwise, need to swap
					for (INT32 j = (INT32)numSortedVerts - 2; j >= 0; j--)
						faceVerts.push_back(sortedVerts[j]);
				}
				else
				{
					// Counterclockwise
					for (int j = 0; j <= (INT32)numSortedVerts - 2; j++)
						faceVerts.push_back(sortedVerts[j]);
				}

				sortedFaces.push_back(faceVerts);
				bs_stack_free(sortedVerts);
			}
		}
	}
コード例 #8
0
	void VulkanGraphicsPipelineState::initialize()
	{
		Lock(mMutex);

		GraphicsPipelineState::initialize();

		std::pair<VkShaderStageFlagBits, GpuProgram*> stages[] =
			{ 
				{ VK_SHADER_STAGE_VERTEX_BIT, mData.vertexProgram.get() },
				{ VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, mData.hullProgram.get() },
				{ VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, mData.domainProgram.get() },
				{ VK_SHADER_STAGE_GEOMETRY_BIT, mData.geometryProgram.get() },
				{ VK_SHADER_STAGE_FRAGMENT_BIT, mData.fragmentProgram.get() }
			};

		UINT32 stageOutputIdx = 0;
		UINT32 numStages = sizeof(stages) / sizeof(stages[0]);
		for(UINT32 i = 0; i < numStages; i++)
		{
			VulkanGpuProgram* program = static_cast<VulkanGpuProgram*>(stages[i].second);
			if (program == nullptr)
				continue;

			VkPipelineShaderStageCreateInfo& stageCI = mShaderStageInfos[stageOutputIdx];
			stageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
			stageCI.pNext = nullptr;
			stageCI.flags = 0;
			stageCI.stage = stages[i].first;
			stageCI.module = VK_NULL_HANDLE;
			stageCI.pName = program->getProperties().getEntryPoint().c_str();
			stageCI.pSpecializationInfo = nullptr;

			stageOutputIdx++;
		}

		UINT32 numUsedStages = stageOutputIdx;

		bool tesselationEnabled = mData.hullProgram != nullptr && mData.domainProgram != nullptr;

		mInputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
		mInputAssemblyInfo.pNext = nullptr;
		mInputAssemblyInfo.flags = 0;
		mInputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; // Assigned at runtime
		mInputAssemblyInfo.primitiveRestartEnable = false;

		mTesselationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
		mTesselationInfo.pNext = nullptr;
		mTesselationInfo.flags = 0;
		mTesselationInfo.patchControlPoints = 3; // Assigned at runtime

		mViewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
		mViewportInfo.pNext = nullptr;
		mViewportInfo.flags = 0;
		mViewportInfo.viewportCount = 1; // Spec says this need to be at least 1...
		mViewportInfo.scissorCount = 1;
		mViewportInfo.pViewports = nullptr; // Dynamic
		mViewportInfo.pScissors = nullptr; // Dynamic

		RasterizerState* rasterizerState = getRasterizerState().get();
		if (rasterizerState == nullptr)
			rasterizerState = RasterizerState::getDefault().get();

		BlendState* blendState = getBlendState().get();
		if (blendState == nullptr)
			blendState = BlendState::getDefault().get();

		DepthStencilState* depthStencilState = getDepthStencilState().get();
		if (depthStencilState == nullptr)
			depthStencilState = DepthStencilState::getDefault().get();

		const RasterizerProperties& rstProps = rasterizerState->getProperties();
		const BlendProperties& blendProps = blendState->getProperties();
		const DepthStencilProperties dsProps = depthStencilState->getProperties();

		mRasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
		mRasterizationInfo.pNext = nullptr;
		mRasterizationInfo.flags = 0;
		mRasterizationInfo.depthClampEnable = !rstProps.getDepthClipEnable();
		mRasterizationInfo.rasterizerDiscardEnable = VK_FALSE;
		mRasterizationInfo.polygonMode = VulkanUtility::getPolygonMode(rstProps.getPolygonMode());
		mRasterizationInfo.cullMode = VulkanUtility::getCullMode(rstProps.getCullMode());
		mRasterizationInfo.frontFace = VK_FRONT_FACE_CLOCKWISE;
		mRasterizationInfo.depthBiasEnable = rstProps.getDepthBias() != 0.0f;
		mRasterizationInfo.depthBiasConstantFactor = rstProps.getDepthBias();
		mRasterizationInfo.depthBiasSlopeFactor = rstProps.getSlopeScaledDepthBias();
		mRasterizationInfo.depthBiasClamp = mRasterizationInfo.depthClampEnable ? rstProps.getDepthBiasClamp() : 0.0f;
		mRasterizationInfo.lineWidth = 1.0f;

		mMultiSampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
		mMultiSampleInfo.pNext = nullptr;
		mMultiSampleInfo.flags = 0;
		mMultiSampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; // Assigned at runtime
		mMultiSampleInfo.sampleShadingEnable = VK_FALSE; // When enabled, perform shading per sample instead of per pixel (more expensive, essentially FSAA)
		mMultiSampleInfo.minSampleShading = 1.0f; // Minimum percent of samples to run full shading for when sampleShadingEnable is enabled (1.0f to run for all)
		mMultiSampleInfo.pSampleMask = nullptr; // Normally one bit for each sample: e.g. 0x0000000F to enable all samples in a 4-sample setup
		mMultiSampleInfo.alphaToCoverageEnable = blendProps.getAlphaToCoverageEnabled();
		mMultiSampleInfo.alphaToOneEnable = VK_FALSE;

		VkStencilOpState stencilFrontInfo;
		stencilFrontInfo.compareOp = VulkanUtility::getCompareOp(dsProps.getStencilFrontCompFunc());
		stencilFrontInfo.depthFailOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontZFailOp());
		stencilFrontInfo.passOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontPassOp());
		stencilFrontInfo.failOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontFailOp());
		stencilFrontInfo.reference = 0; // Dynamic
		stencilFrontInfo.compareMask = (UINT32)dsProps.getStencilReadMask();
		stencilFrontInfo.writeMask = (UINT32)dsProps.getStencilWriteMask();

		VkStencilOpState stencilBackInfo;
		stencilBackInfo.compareOp = VulkanUtility::getCompareOp(dsProps.getStencilBackCompFunc());
		stencilBackInfo.depthFailOp = VulkanUtility::getStencilOp(dsProps.getStencilBackZFailOp());
		stencilBackInfo.passOp = VulkanUtility::getStencilOp(dsProps.getStencilBackPassOp());
		stencilBackInfo.failOp = VulkanUtility::getStencilOp(dsProps.getStencilBackFailOp());
		stencilBackInfo.reference = 0; // Dynamic
		stencilBackInfo.compareMask = (UINT32)dsProps.getStencilReadMask();
		stencilBackInfo.writeMask = (UINT32)dsProps.getStencilWriteMask();

		mDepthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
		mDepthStencilInfo.pNext = nullptr;
		mDepthStencilInfo.flags = 0;
		mDepthStencilInfo.depthBoundsTestEnable = false;
		mDepthStencilInfo.minDepthBounds = 0.0f;
		mDepthStencilInfo.maxDepthBounds = 1.0f;
		mDepthStencilInfo.depthTestEnable = dsProps.getDepthReadEnable();
		mDepthStencilInfo.depthWriteEnable = dsProps.getDepthWriteEnable();
		mDepthStencilInfo.depthCompareOp = VulkanUtility::getCompareOp(dsProps.getDepthComparisonFunc());
		mDepthStencilInfo.front = stencilFrontInfo;
		mDepthStencilInfo.back = stencilBackInfo;
		mDepthStencilInfo.stencilTestEnable = dsProps.getStencilEnable();

		for(UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
		{
			UINT32 rtIdx = 0;
			if (blendProps.getIndependantBlendEnable())
				rtIdx = i;

			VkPipelineColorBlendAttachmentState& blendState = mAttachmentBlendStates[i];
			blendState.blendEnable = blendProps.getBlendEnabled(rtIdx);
			blendState.colorBlendOp = VulkanUtility::getBlendOp(blendProps.getBlendOperation(rtIdx));
			blendState.srcColorBlendFactor = VulkanUtility::getBlendFactor(blendProps.getSrcBlend(rtIdx));
			blendState.dstColorBlendFactor = VulkanUtility::getBlendFactor(blendProps.getDstBlend(rtIdx));
			blendState.alphaBlendOp = VulkanUtility::getBlendOp(blendProps.getAlphaBlendOperation(rtIdx));
			blendState.srcAlphaBlendFactor = VulkanUtility::getBlendFactor(blendProps.getAlphaSrcBlend(rtIdx));
			blendState.dstAlphaBlendFactor = VulkanUtility::getBlendFactor(blendProps.getAlphaDstBlend(rtIdx));
			blendState.colorWriteMask = blendProps.getRenderTargetWriteMask(rtIdx) & 0xF;
		}

		mColorBlendStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
		mColorBlendStateInfo.pNext = nullptr;
		mColorBlendStateInfo.flags = 0;
		mColorBlendStateInfo.logicOpEnable = VK_FALSE;
		mColorBlendStateInfo.logicOp = VK_LOGIC_OP_NO_OP;
		mColorBlendStateInfo.attachmentCount = 0; // Assigned at runtime
		mColorBlendStateInfo.pAttachments = mAttachmentBlendStates;
		mColorBlendStateInfo.blendConstants[0] = 0.0f;
		mColorBlendStateInfo.blendConstants[1] = 0.0f;
		mColorBlendStateInfo.blendConstants[2] = 0.0f;
		mColorBlendStateInfo.blendConstants[3] = 0.0f;

		mDynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT;
		mDynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR;
		mDynamicStates[2] = VK_DYNAMIC_STATE_STENCIL_REFERENCE;

		UINT32 numDynamicStates = sizeof(mDynamicStates) / sizeof(mDynamicStates[0]);
		assert(numDynamicStates == 3);

		mDynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
		mDynamicStateInfo.pNext = nullptr;
		mDynamicStateInfo.flags = 0;
		mDynamicStateInfo.dynamicStateCount = numDynamicStates;
		mDynamicStateInfo.pDynamicStates = mDynamicStates;

		mPipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
		mPipelineInfo.pNext = nullptr;
		mPipelineInfo.flags = 0;
		mPipelineInfo.stageCount = numUsedStages;
		mPipelineInfo.pStages = mShaderStageInfos;
		mPipelineInfo.pVertexInputState = nullptr; // Assigned at runtime
		mPipelineInfo.pInputAssemblyState = &mInputAssemblyInfo;
		mPipelineInfo.pTessellationState = tesselationEnabled ? &mTesselationInfo : nullptr;
		mPipelineInfo.pViewportState = &mViewportInfo;
		mPipelineInfo.pRasterizationState = &mRasterizationInfo;
		mPipelineInfo.pMultisampleState = &mMultiSampleInfo;
		mPipelineInfo.pDepthStencilState = nullptr; // Assigned at runtime
		mPipelineInfo.pColorBlendState = nullptr; // Assigned at runtime
		mPipelineInfo.pDynamicState = &mDynamicStateInfo;
		mPipelineInfo.renderPass = VK_NULL_HANDLE; // Assigned at runtime
		mPipelineInfo.layout = VK_NULL_HANDLE; // Assigned at runtime
		mPipelineInfo.subpass = 0;
		mPipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
		mPipelineInfo.basePipelineIndex = -1;

		mScissorEnabled = rstProps.getScissorEnable();

		if(mData.vertexProgram != nullptr)
			mVertexDecl = mData.vertexProgram->getInputDeclaration();

		VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPI::instance());

		VulkanDevice* devices[BS_MAX_DEVICES];
		VulkanUtility::getDevices(rapi, mDeviceMask, devices);

		for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
		{
			if (devices[i] == nullptr)
				continue;

			mPerDeviceData[i].device = devices[i];

			VulkanDescriptorManager& descManager = mPerDeviceData[i].device->getDescriptorManager();
			VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);

			UINT32 numLayouts = vkParamInfo.getNumSets();
			VulkanDescriptorLayout** layouts = (VulkanDescriptorLayout**)bs_stack_alloc(sizeof(VulkanDescriptorLayout*) * numLayouts);

			for (UINT32 j = 0; j < numLayouts; j++)
				layouts[j] = vkParamInfo.getLayout(i, j);

			mPerDeviceData[i].pipelineLayout = descManager.getPipelineLayout(layouts, numLayouts);

			bs_stack_free(layouts);
		}

		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_PipelineState);
	}
コード例 #9
0
	void VulkanComputePipelineState::initialize()
	{
		ComputePipelineState::initialize();

		// This might happen fairly often if shaders with unsupported languages are loaded, in which case the pipeline
		// will never get used, and its fine not to initialize it.
		if (!mProgram->isCompiled())
			return;

		VulkanGpuProgram* vkProgram = static_cast<VulkanGpuProgram*>(mProgram.get());

		VkPipelineShaderStageCreateInfo stageCI;
		stageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
		stageCI.pNext = nullptr;
		stageCI.flags = 0;
		stageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT;
		stageCI.module = VK_NULL_HANDLE;
		stageCI.pName = vkProgram->getProperties().getEntryPoint().c_str();
		stageCI.pSpecializationInfo = nullptr;

		VkComputePipelineCreateInfo pipelineCI;
		pipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
		pipelineCI.pNext = nullptr;
		pipelineCI.flags = 0;
		pipelineCI.stage = stageCI;
		pipelineCI.basePipelineHandle = VK_NULL_HANDLE;
		pipelineCI.basePipelineIndex = -1;

		VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPI::instance());

		VulkanDevice* devices[BS_MAX_DEVICES];
		VulkanUtility::getDevices(rapi, mDeviceMask, devices);

		for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
		{
			if (devices[i] == nullptr)
				continue;

			mPerDeviceData[i].device = devices[i];

			VulkanDescriptorManager& descManager = devices[i]->getDescriptorManager();
			VulkanResourceManager& rescManager = devices[i]->getResourceManager();
			VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);

			UINT32 numLayouts = vkParamInfo.getNumSets();
			VulkanDescriptorLayout** layouts = (VulkanDescriptorLayout**)bs_stack_alloc(sizeof(VulkanDescriptorLayout*) * numLayouts);

			for (UINT32 j = 0; j < numLayouts; j++)
				layouts[j] = vkParamInfo.getLayout(i, j);

			VulkanShaderModule* module = vkProgram->getShaderModule(i);

			if (module != nullptr)
				pipelineCI.stage.module = module->getHandle();
			else
				pipelineCI.stage.module = VK_NULL_HANDLE;

			pipelineCI.layout = descManager.getPipelineLayout(layouts, numLayouts);

			VkPipeline pipeline;
			VkResult result = vkCreateComputePipelines(devices[i]->getLogical(), VK_NULL_HANDLE, 1, &pipelineCI,
														gVulkanAllocator, &pipeline);
			assert(result == VK_SUCCESS);


			mPerDeviceData[i].pipeline = rescManager.create<VulkanPipeline>(pipeline);
			mPerDeviceData[i].pipelineLayout = pipelineCI.layout;
			bs_stack_free(layouts);
		}

		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_PipelineState);
	}
コード例 #10
0
	void IconUtility::updateIconExe(const Path& path, const Map<UINT32, SPtr<PixelData>>& pixelsPerSize)
	{
		// A PE file is structured as such:
		//  - MSDOS Header
		//  - PE Signature
		//  - COFF Header
		//  - PE Optional Header
		//  - One or multiple sections
		//   - .code
		//   - .data
		//   - ...
		//   - .rsrc
		//    - icon/cursor/etc data

		std::fstream stream;
		stream.open(path.toPlatformString().c_str(), std::ios::in | std::ios::out | std::ios::binary);

		// First check magic number to ensure file is even an executable
		UINT16 magicNum;
		stream.read((char*)&magicNum, sizeof(magicNum));
		if (magicNum != MSDOS_SIGNATURE)
			BS_EXCEPT(InvalidStateException, "Provided file is not a valid executable.");

		// Read the MSDOS header and skip over it
		stream.seekg(0);

		MSDOSHeader msdosHeader;
		stream.read((char*)&msdosHeader, sizeof(MSDOSHeader));

		// Read PE signature
		stream.seekg(msdosHeader.lfanew);

		UINT32 peSignature;
		stream.read((char*)&peSignature, sizeof(peSignature));

		if (peSignature != PE_SIGNATURE)
			BS_EXCEPT(InvalidStateException, "Provided file is not in PE format.");

		// Read COFF header
		COFFHeader coffHeader;
		stream.read((char*)&coffHeader, sizeof(COFFHeader));

		if (coffHeader.sizeOptHeader == 0) // .exe files always have an optional header
			BS_EXCEPT(InvalidStateException, "Provided file is not a valid executable.");

		UINT32 numSectionHeaders = coffHeader.numSections;

		// Read optional header
		auto optionalHeaderPos = stream.tellg();

		UINT16 optionalHeaderSignature;
		stream.read((char*)&optionalHeaderSignature, sizeof(optionalHeaderSignature));

		PEDataDirectory* dataDirectory = nullptr;
		stream.seekg(optionalHeaderPos);
		if (optionalHeaderSignature == PE_32BIT_SIGNATURE)
		{
			PEOptionalHeader32 optionalHeader;
			stream.read((char*)&optionalHeader, sizeof(optionalHeader));

			dataDirectory = optionalHeader.dataDirectory + PE_IMAGE_DIRECTORY_ENTRY_RESOURCE;
		}
		else if (optionalHeaderSignature == PE_64BIT_SIGNATURE)
		{
			PEOptionalHeader64 optionalHeader;
			stream.read((char*)&optionalHeader, sizeof(optionalHeader));

			dataDirectory = optionalHeader.dataDirectory + PE_IMAGE_DIRECTORY_ENTRY_RESOURCE;
		}
		else
			BS_EXCEPT(InvalidStateException, "Unrecognized PE format.");

		// Read section headers
		auto sectionHeaderPos = optionalHeaderPos + (std::ifstream::pos_type)coffHeader.sizeOptHeader;
		stream.seekg(sectionHeaderPos);

		PESectionHeader* sectionHeaders = bs_stack_alloc<PESectionHeader>(numSectionHeaders);
		stream.read((char*)sectionHeaders, sizeof(PESectionHeader) * numSectionHeaders);

		// Look for .rsrc section header
		std::function<void(PEImageResourceDirectory*, PEImageResourceDirectory*, UINT8*, UINT32)> setIconData =
			[&](PEImageResourceDirectory* base, PEImageResourceDirectory* current, UINT8* imageData, UINT32 sectionAddress)
		{
			UINT32 numEntries = current->numIdEntries; // Not supporting name entries
			PEImageResourceEntry* entries = (PEImageResourceEntry*)(current + 1);

			for (UINT32 i = 0; i < numEntries; i++)
			{
				// Only at root does the type identify resource type
				if (base == current && entries[i].type != PE_IMAGE_RT_ICON)
					continue;

				if (entries[i].isDirectory)
				{
					PEImageResourceDirectory* child = (PEImageResourceDirectory*)(((UINT8*)base) + entries[i].offsetDirectory);
					setIconData(base, child, imageData, sectionAddress);
				}
				else
				{
					PEImageResourceEntryData* data = (PEImageResourceEntryData*)(((UINT8*)base) + entries[i].offsetDirectory);

					UINT8* iconData = imageData + (data->offsetData - sectionAddress);
					updateIconData(iconData, pixelsPerSize);
				}
			}
		};

		for (UINT32 i = 0; i < numSectionHeaders; i++)
		{
			if (sectionHeaders[i].flags & PE_SECTION_UNINITIALIZED_DATA)
				continue;

			if (strcmp(sectionHeaders[i].name, ".rsrc") == 0)
			{
				UINT32 imageSize = sectionHeaders[i].physicalSize;
				UINT8* imageData = (UINT8*)bs_stack_alloc(imageSize);

				stream.seekg(sectionHeaders[i].physicalAddress);
				stream.read((char*)imageData, imageSize);

				UINT32 resourceDirOffset = dataDirectory->virtualAddress - sectionHeaders[i].relativeVirtualAddress;
				PEImageResourceDirectory* resourceDirectory = (PEImageResourceDirectory*)&imageData[resourceDirOffset];

				setIconData(resourceDirectory, resourceDirectory, imageData, sectionHeaders[i].relativeVirtualAddress);
				stream.seekp(sectionHeaders[i].physicalAddress);
				stream.write((char*)imageData, imageSize);

				bs_stack_free(imageData);
			}
		}

		bs_stack_free(sectionHeaders);
		stream.close();
	}
コード例 #11
0
	void OAAudioClip::initialize()
	{
		{
			Lock lock(mMutex); // Needs to be called even if stream data is null, to ensure memory fence is added so the
							   // other thread sees properly initialized AudioClip members

			AudioDataInfo info;
			info.bitDepth = mDesc.bitDepth;
			info.numChannels = mDesc.numChannels;
			info.numSamples = mNumSamples;
			info.sampleRate = mDesc.frequency;

			// If we need to keep source data, read everything into memory and keep a copy
			if (mKeepSourceData)
			{
				mStreamData->seek(mStreamOffset);

				UINT8* sampleBuffer = (UINT8*)bs_alloc(mStreamSize);
				mStreamData->read(sampleBuffer, mStreamSize);

				mSourceStreamData = bs_shared_ptr_new<MemoryDataStream>(sampleBuffer, mStreamSize);
				mSourceStreamSize = mStreamSize;
			}

			// Load decompressed data into a sound buffer
			bool loadDecompressed = 
				mDesc.readMode == AudioReadMode::LoadDecompressed || 
				(mDesc.readMode == AudioReadMode::LoadCompressed && mDesc.format == AudioFormat::PCM);

			if(loadDecompressed)
			{
				// Read all data into memory
				SPtr<DataStream> stream;
				UINT32 offset = 0;
				if (mSourceStreamData != nullptr) // If it's already loaded in memory, use it directly
					stream = mSourceStreamData;
				else
				{
					stream = mStreamData;
					offset = mStreamOffset;
				}

				UINT32 bufferSize = info.numSamples * (info.bitDepth / 8);
				UINT8* sampleBuffer = (UINT8*)bs_stack_alloc(bufferSize);

				// Decompress from Ogg
				if (mDesc.format == AudioFormat::VORBIS)
				{
					OggVorbisDecoder reader;
					if (reader.open(stream, info, offset))
						reader.read(sampleBuffer, info.numSamples);
					else
						LOGERR("Failed decompressing AudioClip stream.");
				}
				// Load directly
				else
				{
					stream->seek(offset);
					stream->read(sampleBuffer, bufferSize);
				}

				alGenBuffers(1, &mBufferId);
				gOAAudio()._writeToOpenALBuffer(mBufferId, sampleBuffer, info);

				mStreamData = nullptr;
				mStreamOffset = 0;
				mStreamSize = 0;

				bs_stack_free(sampleBuffer);
			}
			// Load compressed data for streaming from memory
			else if(mDesc.readMode == AudioReadMode::LoadCompressed)
			{
				// If reading from file, make a copy of data in memory, otherwise just take ownership of the existing buffer
				if (mStreamData->isFile()) 
				{
					if (mSourceStreamData != nullptr) // If it's already loaded in memory, use it directly
						mStreamData = mSourceStreamData;
					else
					{
						UINT8* data = (UINT8*)bs_alloc(mStreamSize);

						mStreamData->seek(mStreamOffset);
						mStreamData->read(data, mStreamSize);

						mStreamData = bs_shared_ptr_new<MemoryDataStream>(data, mStreamSize);
					}

					mStreamOffset = 0;
				}
			}
			// Keep original stream for streaming from file
			else
			{
				// Do nothing
			}

			if (mDesc.format == AudioFormat::VORBIS && mDesc.readMode != AudioReadMode::LoadDecompressed)
			{
				mNeedsDecompression = true;

				if (mStreamData != nullptr)
				{
					if (!mVorbisReader.open(mStreamData, info, mStreamOffset))
						LOGERR("Failed decompressing AudioClip stream.");
				}
			}
		}

		AudioClip::initialize();
	}
コード例 #12
0
	void MonoAssembly::load(MonoDomain* domain)
	{
		if (mIsLoaded)
			unload();

		// Load assembly from memory because mono_domain_assembly_open keeps a lock on the file
		SPtr<DataStream> assemblyStream = FileSystem::openFile(mPath, true);
		if (assemblyStream == nullptr)
		{
			LOGERR("Cannot load assembly at path \"" + toString(mPath) + "\" because the file doesn't exist");
			return;
		}

		UINT32 assemblySize = (UINT32)assemblyStream->size();
		char* assemblyData = (char*)bs_stack_alloc(assemblySize);
		assemblyStream->read(assemblyData, assemblySize);

		String imageName = Path(mPath).getFilename();

		MonoImageOpenStatus status = MONO_IMAGE_OK;
		MonoImage* image = mono_image_open_from_data_with_name(assemblyData, assemblySize, true, &status, false, imageName.c_str());
		bs_stack_free(assemblyData);

		if (status != MONO_IMAGE_OK || image == nullptr)
		{
			LOGERR("Failed loading image data for assembly \"" + toString(mPath) + "\"");
			return;
		}

		// Load MDB file
#if BS_DEBUG_MODE
		Path mdbPath = mPath + L".mdb";
		if (FileSystem::exists(mdbPath))
		{
			SPtr<DataStream> mdbStream = FileSystem::openFile(mdbPath, true);

			if (mdbStream != nullptr)
			{
				UINT32 mdbSize = (UINT32)mdbStream->size();
				mDebugData = (UINT8*)bs_alloc(mdbSize);
				mdbStream->read(mDebugData, mdbSize);

				mono_debug_open_image_from_memory(image, mDebugData, mdbSize);
			}
		}
#endif

		mMonoAssembly = mono_assembly_load_from_full(image, imageName.c_str(), &status, false);
		if (status != MONO_IMAGE_OK || mMonoAssembly == nullptr)
		{
			LOGERR("Failed loading assembly \"" + toString(mPath) + "\"");
			return;
		}
		
		mMonoImage = image;
		if(mMonoImage == nullptr)
		{
			BS_EXCEPT(InvalidParametersException, "Cannot get script assembly image.");
		}

		mIsLoaded = true;
		mIsDependency = false;
	}
コード例 #13
0
	void FMODAudioClip::initialize()
	{
		AudioFileInfo info;
		info.bitDepth = mDesc.bitDepth;
		info.numChannels = mDesc.numChannels;
		info.numSamples = mNumSamples;
		info.sampleRate = mDesc.frequency;

		// If we need to keep source data, read everything into memory and keep a copy
		if (mKeepSourceData)
		{
			mStreamData->seek(mStreamOffset);

			UINT8* sampleBuffer = (UINT8*)bs_alloc(mStreamSize);
			mStreamData->read(sampleBuffer, mStreamSize);

			mSourceStreamData = bs_shared_ptr_new<MemoryDataStream>(sampleBuffer, mStreamSize);
			mSourceStreamSize = mStreamSize;
		}

		FMOD::System* fmod = gFMODAudio()._getFMOD();
		FMOD_MODE flags = FMOD_OPENMEMORY;

		if (is3D())
			flags |= FMOD_3D;
		else
			flags |= FMOD_2D;

		// Load data into a sound buffer
		// TODO - Vorbis cannot be decompressed from memory by FMOD. Instead we force AudioReadMode::Stream for it.
		if(mDesc.readMode == AudioReadMode::LoadDecompressed || 
			(mDesc.readMode == AudioReadMode::LoadCompressed && mDesc.format != AudioFormat::VORBIS))
		{
			// Read all data into memory
			SPtr<DataStream> stream;
			UINT32 offset = 0;
			if (mSourceStreamData != nullptr) // If it's already loaded in memory, use it directly
				stream = mSourceStreamData;
			else
			{
				stream = mStreamData;
				offset = mStreamOffset;
			}

			UINT32 bufferSize = info.numSamples * (info.bitDepth / 8);
			UINT8* sampleBuffer = (UINT8*)bs_stack_alloc(bufferSize);

			stream->seek(offset);
			stream->read(sampleBuffer, bufferSize);

			FMOD_CREATESOUNDEXINFO exInfo;
			memset(&exInfo, 0, sizeof(exInfo));
			exInfo.cbsize = sizeof(exInfo);
			exInfo.length = bufferSize;

			bool loadCompressed = mDesc.readMode == AudioReadMode::LoadCompressed && mDesc.format != AudioFormat::PCM;

			if (loadCompressed)
				flags |= FMOD_CREATECOMPRESSEDSAMPLE;
			else
				flags |= FMOD_CREATESAMPLE;

			if(fmod->createSound((const char*)sampleBuffer, flags, &exInfo, &mSound) != FMOD_OK)
			{
				LOGERR("Failed playing sound.");
			}
			else
			{
				mSound->setMode(FMOD_LOOP_OFF);
			}

			mStreamData = nullptr;
			mStreamOffset = 0;
			mStreamSize = 0;

			bs_stack_free(sampleBuffer);
		}
		else // Streaming
		{
			// Do nothing, we rely on AudioSource from creating sounds as only one streaming sound can ever be playing
		}

		AudioClip::initialize();
	}
コード例 #14
0
	void GLSLGpuProgram::initialize()
	{

#if BS_OPENGL_4_5
		static const char* VERSION_CHARS = "450";
#elif BS_OPENGL_4_4
		static const char* VERSION_CHARS = "440";
#elif BS_OPENGL_4_3
		static const char* VERSION_CHARS = "430";
#elif BS_OPENGL_4_2
		static const char* VERSION_CHARS = "420";
#else
		static const char* VERSION_CHARS = "410";
#endif
		
		if (!isSupported())
		{
			mIsCompiled = false;
			mCompileMessages = "Specified GPU program type is not supported by the current render system.";

			GpuProgram::initialize();
			return;
		}

		GLenum shaderType = 0x0000;
		switch (mType)
		{
		case GPT_VERTEX_PROGRAM:
			shaderType = GL_VERTEX_SHADER;
			mProgramID = ++sVertexShaderCount;
			break;
		case GPT_FRAGMENT_PROGRAM:
			shaderType = GL_FRAGMENT_SHADER;
			mProgramID = ++sFragmentShaderCount;
			break;
#if BS_OPENGL_4_1 || BS_OPENGLES_3_2
		case GPT_GEOMETRY_PROGRAM:
			shaderType = GL_GEOMETRY_SHADER;
			mProgramID = ++sGeometryShaderCount;
			break;
		case GPT_HULL_PROGRAM:
			shaderType = GL_TESS_CONTROL_SHADER;
			mProgramID = ++sDomainShaderCount;
			break;
		case GPT_DOMAIN_PROGRAM:
			shaderType = GL_TESS_EVALUATION_SHADER;
			mProgramID = ++sHullShaderCount;
			break;
#endif
#if BS_OPENGL_4_3 || BS_OPENGLES_3_1
		case GPT_COMPUTE_PROGRAM:
			shaderType = GL_COMPUTE_SHADER;
			mProgramID = ++sComputeShaderCount;
			break;
#endif
		default:
			break;
		}

		// Add preprocessor extras and main source
		const String& source = mSource;
		if (!source.empty())
		{
			Vector<GLchar*> lines;

			const char* versionStr = "#version ";
			UINT32 versionStrLen = (UINT32)strlen(versionStr);

			UINT32 lineLength = 0;
			INT32 versionLineNum = -1;
			for (UINT32 i = 0; i < source.size(); i++)
			{
				if (source[i] == '\n' || source[i] == '\r')
				{
					assert(sizeof(source[i]) == sizeof(GLchar));

					GLchar* lineData = (GLchar*)bs_stack_alloc(sizeof(GLchar) * (lineLength + 2));
					memcpy(lineData, &source[i - lineLength], sizeof(GLchar) * lineLength);

					lineData[lineLength] = '\n';
					lineData[lineLength + 1] = '\0';

					if(versionLineNum == -1 && lineLength >= versionStrLen)
					{
						bool isEqual = true;
						for (UINT32 j = 0; j < versionStrLen; ++j)
						{
							if(lineData[j] != versionStr[j])
							{
								isEqual = false;
								break;
							}
						}

						if (isEqual)
							versionLineNum = (INT32)lines.size();
					}

					lines.push_back(lineData);
					lineLength = 0;
				}
				else
				{
					lineLength++;
				}
			}

			if (lineLength > 0)
			{
				UINT32 end = (UINT32)source.size() - 1;
				assert(sizeof(source[end]) == sizeof(GLchar));

				GLchar* lineData = (GLchar*)bs_stack_alloc(sizeof(GLchar) * (lineLength + 1));
				memcpy(lineData, &source[source.size() - lineLength], sizeof(GLchar) * lineLength);
				lineData[lineLength] = '\0';

				lines.push_back(lineData);
				lineLength = 0;
			}

			int numInsertedLines = 0;
			if(versionLineNum == -1)
			{
				char versionLine[50];
				strcpy(versionLine, "#version ");
				strcat(versionLine, VERSION_CHARS);
				strcat(versionLine, "\n");

				UINT32 length = (UINT32)strlen(versionLine) + 1;

				GLchar* extraLineData = (GLchar*)bs_stack_alloc(length);
				memcpy(extraLineData, versionLine, length);

				lines.insert(lines.begin(), extraLineData);
				numInsertedLines++;
			}

			char versionDefine[50];
			strcpy(versionDefine, "#define OPENGL");
			strcat(versionDefine, VERSION_CHARS);
			strcat(versionDefine, "\n");

			const char* EXTRA_LINES[] =
				{ 
					"#define OPENGL\n",
					versionDefine
				};

			UINT32 numExtraLines = sizeof(EXTRA_LINES) / sizeof(EXTRA_LINES[0]);
			UINT32 extraLineOffset = versionLineNum != -1 ? versionLineNum + 1 : 0;
			for (UINT32 i = 0; i < numExtraLines; i++)
			{
				UINT32 length = (UINT32)strlen(EXTRA_LINES[i]) + 1;

				GLchar* extraLineData = (GLchar*)bs_stack_alloc(length);
				memcpy(extraLineData, EXTRA_LINES[i], length);

				lines.insert(lines.begin() + extraLineOffset + numInsertedLines, extraLineData);
				numInsertedLines++;
			}

			StringStream codeStream;
			for(auto& entry : lines)
				codeStream << entry;

			for (INT32 i = numInsertedLines - 1; i >= 0; i--)
				bs_stack_free(lines[extraLineOffset + i]);

			if (numInsertedLines > 0)
				lines.erase(lines.begin() + extraLineOffset, lines.begin() + extraLineOffset + numInsertedLines);

			for (auto iter = lines.rbegin(); iter != lines.rend(); ++iter)
				bs_stack_free(*iter);

			String code = codeStream.str();
			const char* codeRaw = code.c_str();
			mGLHandle = glCreateShaderProgramv(shaderType, 1, (const GLchar**)&codeRaw);
			BS_CHECK_GL_ERROR();

			mCompileMessages = "";
			mIsCompiled = !checkForGLSLError(mGLHandle, mCompileMessages);
		}

		if (mIsCompiled)
		{
			GLSLParamParser paramParser;
			paramParser.buildUniformDescriptions(mGLHandle, mType, *mParametersDesc);

			if (mType == GPT_VERTEX_PROGRAM)
			{
				Vector<VertexElement> elementList = paramParser.buildVertexDeclaration(mGLHandle);
				mInputDeclaration = HardwareBufferManager::instance().createVertexDeclaration(elementList);
			}
		}

		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_GpuProgram);
		GpuProgram::initialize();
	}