Application::Application() :
	window(new Window(1280, 720, L"testerata!")),
	device(new D3D12Device(*window)),
	frameQueueIndex(0)
{
	// Create a command allocator for every inflight-frame
	for (int i = 0; i < D3D12Device::MAX_FRAMES_INFLIGHT; ++i)
	{
		if (FAILED(device->GetD3D12Device()->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&commandAllocator[i]))))
			CRITICAL_ERROR("Failed to create command list allocator.");
	}
	// Create the command list.
	if (FAILED(device->GetD3D12Device()->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAllocator[frameQueueIndex].Get(), pso.Get(), IID_PPV_ARGS(&commandList))))
		CRITICAL_ERROR("Failed to create command list");
	commandList->Close();

	CreateRootSignature();
	CreatePSO();
	CreateVertexBuffer();
	CreateTextures();

	// Configure viewport and scissor rect.
	viewport.TopLeftX = 0.0f;
	viewport.TopLeftY = 0.0f;
	viewport.Width = static_cast<float>(window->GetWidth());
	viewport.Height = static_cast<float>(window->GetHeight());
	viewport.MinDepth = 0.0f;
	viewport.MaxDepth = 1.0f;
	scissorRect.left = 0;
	scissorRect.top = 0;
	scissorRect.right = static_cast<LONG>(window->GetWidth());
	scissorRect.bottom = static_cast<LONG>(window->GetHeight());
}
Пример #2
0
// ------------------------------------------------------------------------- //
// NAME: Run
//
// per thread / same thread as caller - initiate a new thread
//
// ------------------------------------------------------------------------- //
ESTDLTResults
CSysThread::Run(
	EThreadPriority pri
	) 
{
	m_hThread = (HANDLE)_beginthreadex(
							NULL,						// security
							THREAD_STACK_SIZE,			// stack size
							&CSysThread::ThreadLaunch,  // start address
							(void *)this,				// arg list
							CREATE_SUSPENDED,			// init flag (0 == running, CREATE_SUSPENDED == suspended)
							&m_ThreadID);
	if (m_hThread != 0)
	{
		//
		// We create each thread suspended in case the current thread
		// is at very low priority and we might get starved before 
		// we have a chance to set it's priority.
		//
		if (pri != ThreadNormal)
			SetThreadPriority(m_hThread, LTPriToWinPri(pri));
		//
		// Off to the races...
		//
		if (ResumeThread(m_hThread) == 0xffffffff)
		{
			CRITICAL_ERROR ("CSysThread::Run","Can't resume thread\n");
			return STDLT_ERROR;
		}
		return STDLT_OK;
	}

	CRITICAL_ERROR("CSysThread::Run","Can't create thread\n");
	return STDLT_ERROR;
} // CSysThread::Run
void Application::CreateVertexBuffer()
{
	struct Vertex
	{
		float position[2];
		float texcoord[2];
	};

	// Define the geometry for a quad.
	float screenAspectRatio = static_cast<float>(window->GetWidth()) / window->GetHeight();
	Vertex quadVertices[] =
	{
		{ { -0.25f, -0.25f * screenAspectRatio }, { 0.0f, 0.0f } },
		{ { -0.25f, 0.25f * screenAspectRatio },{ 0.0f, 1.0f } },
		{ { 0.25f, -0.25f * screenAspectRatio },{ 1.0f, 0.0f } },
		{ { 0.25f, 0.25f * screenAspectRatio },{ 1.0f, 1.0f } }
	};

	const unsigned int vertexBufferSize = sizeof(quadVertices);

	// Create an upload heap for the
	ComPtr<ID3D12Resource> uploadHeap;
	if (FAILED(device->GetD3D12Device()->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE,
																&CD3DX12_RESOURCE_DESC::Buffer(sizeof(quadVertices)), D3D12_RESOURCE_STATE_GENERIC_READ, // D3D12_RESOURCE_STATE_GENERIC_READ is the only possible for D3D12_HEAP_TYPE_UPLOAD.
																nullptr, IID_PPV_ARGS(&uploadHeap))))
	{
		CRITICAL_ERROR("Failed to create upload heap.");
	}

	// Copy the triangle data to the vertex buffer.
	UINT8* pVertexDataBegin;
	if (FAILED(uploadHeap->Map(0, nullptr, reinterpret_cast<void**>(&pVertexDataBegin))))
		CRITICAL_ERROR("Failed to map vertex buffer");
	memcpy(pVertexDataBegin, quadVertices, sizeof(quadVertices));
	uploadHeap->Unmap(0, nullptr);

	// Create vertex buffer.
	if (FAILED(device->GetD3D12Device()->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE,
																&CD3DX12_RESOURCE_DESC::Buffer(sizeof(quadVertices)), D3D12_RESOURCE_STATE_COPY_DEST,
																nullptr, IID_PPV_ARGS(&vertexBuffer))))
	{
		CRITICAL_ERROR("Failed to create vertex buffer.");
	}

	// Copy over and wait until its done.
	commandList->Reset(commandAllocator[0].Get(), nullptr);
	commandList->CopyResource(vertexBuffer.Get(), uploadHeap.Get());
	commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(vertexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER));
	commandList->Close();
	ID3D12CommandList* ppCommandLists[] = { commandList.Get() };
	device->GetDirectCommandQueue()->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
	device->WaitForIdleGPU();

	// Initialize the vertex buffer view.
	vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress();
	vertexBufferView.StrideInBytes = sizeof(Vertex);
	vertexBufferView.SizeInBytes = vertexBufferSize;
}
void Application::CreateRootSignature()
{	
	D3D12_DESCRIPTOR_RANGE ranges[1];
	ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
	ranges[0].NumDescriptors = 1;
	ranges[0].BaseShaderRegister = 0;
	ranges[0].RegisterSpace = 0;
	ranges[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
	//D3DX: ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);


	D3D12_ROOT_PARAMETER rootParameters[2];
	rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; // Would also be possible to create a shader resource view right away, since we have only one texture. But for practicing we use a table.
	rootParameters[0].DescriptorTable.NumDescriptorRanges = 1;
	rootParameters[0].DescriptorTable.pDescriptorRanges = ranges;
	rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;

	rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
	rootParameters[1].Constants.ShaderRegister = 0;
	rootParameters[1].Constants.RegisterSpace = 0;
	rootParameters[1].Constants.Num32BitValues = 1;
	rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;


	D3D12_STATIC_SAMPLER_DESC sampler = {};
	sampler.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
	sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
	sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
	sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
	sampler.MipLODBias = 0;
	sampler.MaxAnisotropy = 0;
	sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
	sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
	sampler.MinLOD = 0.0f;
	sampler.MaxLOD = D3D12_FLOAT32_MAX;
	sampler.ShaderRegister = 0;
	sampler.RegisterSpace = 0;
	sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;

	D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
	rootSignatureDesc.NumParameters = 2;
	rootSignatureDesc.pParameters = rootParameters;
	rootSignatureDesc.NumStaticSamplers = 1;
	rootSignatureDesc.pStaticSamplers = &sampler;
	rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;


	ComPtr<ID3DBlob> signature;
	ComPtr<ID3DBlob> error;
	if (FAILED(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)))
	{
		OutputDXError(error.Get());
		CRITICAL_ERROR("Failed to serialize root signature.");
	}
	if (FAILED(device->GetD3D12Device()->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&rootSignature))))
		CRITICAL_ERROR("Failed to createroot signature");
}
Пример #5
0
ESTDLTResults
CGenUnboundData::Init () {
	uint32* tmpPtr;
	uint32  blockSizeInWords;

	// Figure out a better way to deal with dynamic block Size
	CurBlockSize = 512; // 1/2 K block size
	blockSizeInWords = CurBlockSize/4;

	// init stat counters
	GetCnt = RetCnt = 0;

	// first grab a big chunck of memory and thread it together to form
	// your freelist
	if (initUnboundHeap(CurBlockSize, &heapStart, &heapEnd) != STDLT_OK) {
		CRITICAL_ERROR("undata.cpp", "Couldn't allocate heap\n");
	}

	// Assumes that heapStart addess is numerically lower than heapEnd
	for (tmpPtr = heapEnd-blockSizeInWords, FreeListHead = NULL, FreeBlocks = 0;
	     tmpPtr >= heapStart;
		 tmpPtr -= blockSizeInWords) {
		*tmpPtr = (uint32) FreeListHead;
		FreeListHead = tmpPtr;
		FreeBlocks++;
	}
	minFreeBlocks = FreeBlocks;

	assert (FreeListHead != NULL);
	return (STDLT_OK);
}
Пример #6
0
/** @brief Discard a range of buffers, marking them invalid.

    @param ulBlockStart The starting block number to discard
    @param ulBlockCount The number of blocks, starting at @p ulBlockStart, to
                        discard.  Must not be zero.

    @return A negated ::REDSTATUS code indicating the operation result.

    @retval 0           Operation was successful.
    @retval -RED_EINVAL Invalid parameters.
    @retval -RED_EBUSY  A block in the desired range is referenced.
*/
REDSTATUS RedBufferDiscardRange(
    uint32_t    ulBlockStart,
    uint32_t    ulBlockCount)
{
    REDSTATUS   ret = 0;

    if(    (ulBlockStart >= gpRedVolume->ulBlockCount)
        || ((gpRedVolume->ulBlockCount - ulBlockStart) < ulBlockCount)
        || (ulBlockCount == 0U))
    {
        REDERROR();
        ret = -RED_EINVAL;
    }
    else
    {
        uint8_t bIdx;

        for(bIdx = 0U; bIdx < REDCONF_BUFFER_COUNT; bIdx++)
        {
            BUFFERHEAD *pHead = &gBufCtx.aHead[bIdx];

            if(    (pHead->bVolNum == gbRedVolNum)
                && (pHead->ulBlock != BBLK_INVALID)
                && (pHead->ulBlock >= ulBlockStart)
                && (pHead->ulBlock < (ulBlockStart + ulBlockCount)))
            {
                if(pHead->bRefCount == 0U)
                {
                    pHead->ulBlock = BBLK_INVALID;

                    BufferMakeLRU(bIdx);
                }
                else
                {
                    /*  This should never happen.  There are three general cases
                        when this function is used:

                        1) Discarding every block, as happens during unmount
                           and at the end of format.  There should no longer be
                           any referenced buffers at those points.
                        2) Discarding a block which has become free.  All
                           buffers for such blocks should be put or branched
                           beforehand.
                        3) Discarding of blocks that were just written straight
                           to disk, leaving stale data in the buffer.  The write
                           code should never reference buffers for these blocks,
                           since they would not be needed or used.
                    */
                    CRITICAL_ERROR();
                    ret = -RED_EBUSY;
                    break;
                }
            }
        }
    }

    return ret;
}
void Application::PopulateCommandList()
{
	// Should be completely save now to reset this command allocator.
	if (FAILED(commandAllocator[frameQueueIndex]->Reset()))
		CRITICAL_ERROR("Failed to reset the command allocator.");
	// Restart command queue with new command allocator (last frame a different was used)
	if(FAILED(commandList->Reset(commandAllocator[frameQueueIndex].Get(), pso.Get())))
		CRITICAL_ERROR("Failed to reset the command list.");

	// Set necessary state.
	commandList->SetGraphicsRootSignature(rootSignature.Get());
	commandList->RSSetViewports(1, &viewport);
	commandList->RSSetScissorRects(1, &scissorRect);

	// Indicate that the back buffer will be used as a render target.
	commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(device->GetCurrentSwapChainBuffer(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
	auto rtvDesc = device->GetCurrentSwapChainBufferRTVDesc();
	commandList->OMSetRenderTargets(1, &rtvDesc, FALSE, nullptr);

	// Record commands.
	const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
	commandList->ClearRenderTargetView(rtvDesc, clearColor, 0, nullptr);
	commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
	commandList->IASetVertexBuffers(0, 1, &vertexBufferView);
	ID3D12DescriptorHeap* descriptorHeaps[] = { textureDescriptorHeap.Get() };
	commandList->SetDescriptorHeaps(1, descriptorHeaps);

	auto textureDescHandle = textureDescriptorHeap->GetGPUDescriptorHandleForHeapStart();
	for (int i = 0; i < numTextures; ++i)
	{
		commandList->SetGraphicsRootDescriptorTable(0, textureDescHandle);
		commandList->SetGraphicsRoot32BitConstant(1, i, 0);
		commandList->DrawInstanced(4, 1, 0, 0);
		textureDescHandle.ptr += device->GetDescriptorSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
	}

	// Indicate that the back buffer will now be used to present.
	commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(device->GetCurrentSwapChainBuffer(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));

	if (FAILED(commandList->Close()))
		CRITICAL_ERROR("Failed to close the command list.");
}
Пример #8
0
/** @brief Determine which copy of the inode is currently writeable.

    @param ulInode  The inode number to examine.
    @param pbWhich  On successful return, populated with which copy of the inode
                    (either 0 or 1) is writeable.

    @return A negated ::REDSTATUS code indicating the operation result.

    @retval 0           Operation was successful.
    @retval -RED_EINVAL @p pbWhich is `NULL`; or ulInode is not a valid inode
                        number.
    @retval -RED_EIO    A disk I/O error occurred.
*/
static REDSTATUS InodeGetWriteableCopy(
    uint32_t    ulInode,
    uint8_t    *pbWhich)
{
    REDSTATUS   ret;

    if(pbWhich == NULL)
    {
        REDERROR();
        ret = -RED_EINVAL;
    }
    else
    {
        bool fSlot0Allocated;

        /*  The writeable inode slot is the one which is free in the committed
            state, so query the committed state metaroot.
        */
        ret = RedInodeBitGet(1U - gpRedCoreVol->bCurMR, ulInode, 0U, &fSlot0Allocated);

        if(ret == 0)
        {
            if(!fSlot0Allocated)
            {
                *pbWhich = 0U;
            }
            else
            {
                bool fSlot1Allocated;

                ret = RedInodeBitGet(1U - gpRedCoreVol->bCurMR, ulInode, 1U, &fSlot1Allocated);

                if(ret == 0)
                {
                    if(!fSlot1Allocated)
                    {
                        *pbWhich = 1U;
                    }
                    else
                    {
                        /*  Both inode slots were allocated, which should never
                            happen.
                        */
                        CRITICAL_ERROR();
                        ret = -RED_EFUBAR;
                    }
                }
            }
        }
    }

    return ret;
}
Пример #9
0
/** @brief Set the allocation bit of a block in the working-state imap.

    @param ulBlock      The block number to allocate or free.
    @param fAllocated   Whether to allocate the block (true) or free it (false).

    @return A negated ::REDSTATUS code indicating the operation result.

    @retval 0           Operation was successful.
    @retval -RED_EINVAL @p ulBlock is out of range.
    @retval -RED_EIO    A disk I/O error occurred.
*/
REDSTATUS RedImapEBlockSet(
    uint32_t    ulBlock,
    bool        fAllocated)
{
    REDSTATUS   ret;

    if(    gpRedCoreVol->fImapInline
        || (ulBlock < gpRedCoreVol->ulInodeTableStartBN)
        || (ulBlock >= gpRedVolume->ulBlockCount))
    {
        REDERROR();
        ret = -RED_EINVAL;
    }
    else
    {
        uint32_t    ulOffset = ulBlock - gpRedCoreVol->ulInodeTableStartBN;
        uint32_t    ulImapNode = ulOffset / IMAPNODE_ENTRIES;
        IMAPNODE   *pImap;

        ret = ImapNodeBranch(ulImapNode, &pImap);

        if(ret == 0)
        {
            uint32_t ulImapEntry = ulOffset % IMAPNODE_ENTRIES;

            if(RedBitGet(pImap->abEntries, ulImapEntry) == fAllocated)
            {
                /*  The driver shouldn't ever set a bit in the imap to its
                    current value.  That shouldn't ever be needed, and it
                    indicates that the driver is doing unnecessary I/O, or
                    that the imap is corrupt.
                */
                CRITICAL_ERROR();
                ret = -RED_EFUBAR;
            }
            else if(fAllocated)
            {
                RedBitSet(pImap->abEntries, ulImapEntry);
            }
            else
            {
                RedBitClear(pImap->abEntries, ulImapEntry);
            }

            RedBufferPut(pImap);
        }
    }

    return ret;
}
Пример #10
0
/** @brief Find a free inode number.

    @param pulInode On successful return, populated with a free inode number.

    @return A negated ::REDSTATUS code indicating the operation result.

    @retval 0           Operation was successful.
    @retval -RED_EINVAL @p pulInode is `NULL`.
    @retval -RED_EIO    A disk I/O error occurred.
    @retval -RED_ENFILE No available inode numbers.
*/
static REDSTATUS InodeFindFree(
    uint32_t   *pulInode)
{
    REDSTATUS   ret;

    if(pulInode == NULL)
    {
        REDERROR();
        ret = -RED_EINVAL;
    }
    else if(gpRedMR->ulFreeInodes == 0U)
    {
        ret = -RED_ENFILE;
    }
    else
    {
        uint32_t ulInode;

        ret = 0;

        for(ulInode = INODE_FIRST_FREE; ulInode < (INODE_FIRST_VALID + gpRedVolConf->ulInodeCount); ulInode++)
        {
            bool fFree;

            ret = RedInodeIsFree(ulInode, &fFree);

            if((ret != 0) || fFree)
            {
                break;
            }
        }

        if(ret == 0)
        {
            if(ulInode < (INODE_FIRST_VALID + gpRedVolConf->ulInodeCount))
            {
                *pulInode = ulInode;
            }
            else
            {
                /*  If gpRedMR->ulFreeInodes > 0, we should have found an inode.
                */
                CRITICAL_ERROR();
                ret = -RED_ENFILE;
            }
        }
    }

    return ret;
}
Пример #11
0
/** @brief Increment the sequence number.

    @return A negated ::REDSTATUS code indicating the operation result.

    @retval 0           Operation was successful.
    @retval -RED_EINVAL Cannot increment sequence number: maximum value reached.
                        This should not ever happen.
*/
REDSTATUS RedVolSeqNumIncrement(void)
{
    REDSTATUS ret;

    if(gpRedVolume->ullSequence == UINT64_MAX)
    {
        /*  In practice this should never, ever happen; to get here, there would
            need to be UINT64_MAX disk writes, which would take eons: longer
            than the lifetime of any product or storage media.  If this assert
            fires and the current year is still written with four digits,
            suspect memory corruption.
        */
        CRITICAL_ERROR();
        ret = -RED_EFUBAR;
    }
    else
    {
        gpRedVolume->ullSequence++;
        ret = 0;
    }

    return ret;
}
Пример #12
0
/** @brief Acquire a buffer.

    @param ulBlock  Block number to acquire.
    @param uFlags   BFLAG_ values for the operation.
    @param ppBuffer On success, populated with the acquired buffer.

    @return A negated ::REDSTATUS code indicating the operation result.

    @retval 0           Operation was successful.
    @retval -RED_EIO    A disk I/O error occurred.
    @retval -RED_EINVAL Invalid parameters.
    @retval -RED_EBUSY  All buffers are referenced.
*/
REDSTATUS RedBufferGet(
    uint32_t    ulBlock,
    uint16_t    uFlags,
    void      **ppBuffer)
{
    REDSTATUS   ret = 0;
    uint8_t     bIdx;

    if((ulBlock >= gpRedVolume->ulBlockCount) || ((uFlags & BFLAG_MASK) != uFlags) || (ppBuffer == NULL))
    {
        REDERROR();
        ret = -RED_EINVAL;
    }
    else
    {
        if(BufferFind(ulBlock, &bIdx))
        {
            /*  Error if the buffer exists and BFLAG_NEW was specified, since
                the new flag is used when a block is newly allocated/created, so
                the block was previously free and and there should never be an
                existing buffer for a free block.

                Error if the buffer exists but does not have the same type as
                was requested.
            */
            if(    ((uFlags & BFLAG_NEW) != 0U)
                || ((uFlags & BFLAG_META_MASK) != (gBufCtx.aHead[bIdx].uFlags & BFLAG_META_MASK)))
            {
                CRITICAL_ERROR();
                ret = -RED_EFUBAR;
            }
        }
        else if(gBufCtx.uNumUsed == REDCONF_BUFFER_COUNT)
        {
            /*  The MINIMUM_BUFFER_COUNT is supposed to ensure that no operation
                ever runs out of buffers, so this should never happen.
            */
            CRITICAL_ERROR();
            ret = -RED_EBUSY;
        }
        else
        {
            BUFFERHEAD *pHead;

            /*  Search for the least recently used buffer which is not
                referenced.
            */
            for(bIdx = (uint8_t)(REDCONF_BUFFER_COUNT - 1U); bIdx > 0U; bIdx--)
            {
                if(gBufCtx.aHead[gBufCtx.abMRU[bIdx]].bRefCount == 0U)
                {
                    break;
                }
            }

            bIdx = gBufCtx.abMRU[bIdx];
            pHead = &gBufCtx.aHead[bIdx];

            if(pHead->bRefCount == 0U)
            {
                /*  If the LRU buffer is valid and dirty, write it out before
                    repurposing it.
                */
                if(((pHead->uFlags & BFLAG_DIRTY) != 0U) && (pHead->ulBlock != BBLK_INVALID))
                {
                  #if REDCONF_READ_ONLY == 1
                    CRITICAL_ERROR();
                    ret = -RED_EFUBAR;
                  #else
                    ret = BufferWrite(bIdx);
                  #endif
                }
            }
            else
            {
                /*  All the buffers are used, which should have been caught by
                    checking gBufCtx.uNumUsed.
                */
                CRITICAL_ERROR();
                ret = -RED_EBUSY;
            }

            if(ret == 0)
            {
                if((uFlags & BFLAG_NEW) == 0U)
                {
                    /*  Invalidate the LRU buffer.  If the read fails, we do not
                        want the buffer head to continue to refer to the old
                        block number, since the read, even if it fails, may have
                        partially overwritten the buffer data (consider the case
                        where block size exceeds sector size, and some but not
                        all of the sectors are read successfully), and if the
                        buffer were to be used subsequently with its partially
                        erroneous contents, bad things could happen.
                    */
                    pHead->ulBlock = BBLK_INVALID;

                    ret = RedIoRead(gbRedVolNum, ulBlock, 1U, gBufCtx.b.aabBuffer[bIdx]);

                    if((ret == 0) && ((uFlags & BFLAG_META) != 0U))
                    {
                        if(!BufferIsValid(gBufCtx.b.aabBuffer[bIdx], uFlags))
                        {
                            /*  A corrupt metadata node is usually a critical
                                error.  The master block is an exception since
                                it might be invalid because the volume is not
                                mounted; that condition is expected and should
                                not result in an assertion.
                            */
                            CRITICAL_ASSERT((uFlags & BFLAG_META_MASTER) == BFLAG_META_MASTER);
                            ret = -RED_EIO;
                        }
                    }

                  #ifdef REDCONF_ENDIAN_SWAP
                    if(ret == 0)
                    {
                        BufferEndianSwap(gBufCtx.b.aabBuffer[bIdx], uFlags);
                    }
                  #endif
                }
                else
                {
                    RedMemSet(gBufCtx.b.aabBuffer[bIdx], 0U, REDCONF_BLOCK_SIZE);
                }
            }

            if(ret == 0)
            {
                pHead->bVolNum = gbRedVolNum;
                pHead->ulBlock = ulBlock;
                pHead->uFlags = 0U;
            }
        }

        /*  Reference the buffer, update its flags, and promote it to MRU.  This
            happens both when BufferFind() found an existing buffer for the
            block and when the LRU buffer was repurposed to create a buffer for
            the block.
        */
        if(ret == 0)
        {
            BUFFERHEAD *pHead = &gBufCtx.aHead[bIdx];

            pHead->bRefCount++;

            if(pHead->bRefCount == 1U)
            {
                gBufCtx.uNumUsed++;
            }

            /*  BFLAG_NEW tells this function to zero the buffer instead of
                reading it from disk; it has no meaning later on, and thus is
                not saved.
            */
            pHead->uFlags |= (uFlags & (~BFLAG_NEW));

            BufferMakeMRU(bIdx);

            *ppBuffer = gBufCtx.b.aabBuffer[bIdx];
        }
    }

    return ret;
}
Пример #13
0
/** @brief Mount an existing inode.

    Will populate all fields of the cached inode structure, except those which
    are populated during seek.

    @param pInode   A pointer to the cached inode structure.  The
                    pInode->ulInode field must already be initialized with the
                    inode number to mount.  All other fields will be discarded.
    @param type     The expected inode type.
    @param fBranch  Whether to branch the inode.

    @return A negated ::REDSTATUS code indicating the operation result.

    @retval 0               Operation was successful.
    @retval -RED_EINVAL     Invalid parameters.
    @retval -RED_EROFS      @p fBranch is true but the driver is read-only.
    @retval -RED_EIO        A disk I/O error occurred.
    @retval -RED_EBADF      The inode number is free; or the inode number is not
                            valid.
    @retval -RED_EISDIR     @p type is ::FTYPE_FILE and the inode is a directory.
    @retval -RED_ENOTDIR    @p type is ::FTYPE_DIR and the inode is a file.
*/
REDSTATUS RedInodeMount(
    CINODE     *pInode,
    FTYPE       type,
    bool        fBranch)
{
    REDSTATUS   ret = 0;

    if(pInode == NULL)
    {
        ret = -RED_EINVAL;
    }
    else if(!INODE_IS_VALID(pInode->ulInode))
    {
        ret = -RED_EBADF;
    }
  #if REDCONF_API_FSE == 1
    else if(type == FTYPE_DIR)
    {
        REDERROR();
        ret = -RED_EINVAL;
    }
  #endif
  #if REDCONF_READ_ONLY == 1
    else if(fBranch)
    {
        REDERROR();
        ret = -RED_EROFS;
    }
  #endif
    else
    {
        uint32_t ulInode = pInode->ulInode;
        uint8_t  bWhich = 0U; /* Init'd to quiet warnings. */

        RedMemSet(pInode, 0U, sizeof(*pInode));
        pInode->ulInode = ulInode;

        ret = InodeGetCurrentCopy(pInode->ulInode, &bWhich);

        if(ret == 0)
        {
            ret = RedBufferGet(InodeBlock(pInode->ulInode, bWhich), BFLAG_META_INODE, CAST_VOID_PTR_PTR(&pInode->pInodeBuf));
        }

      #if REDCONF_READ_ONLY == 0
        if(ret == 0)
        {
            ret = InodeIsBranched(pInode->ulInode, &pInode->fBranched);
        }
      #endif

        if(ret == 0)
        {
            if(RED_S_ISREG(pInode->pInodeBuf->uMode))
            {
              #if REDCONF_API_POSIX == 1
                pInode->fDirectory = false;

                if(type == FTYPE_DIR)
                {
                    ret = -RED_ENOTDIR;
                }
              #endif
            }
          #if REDCONF_API_POSIX == 1
            else if(RED_S_ISDIR(pInode->pInodeBuf->uMode))
            {
                pInode->fDirectory = true;

                if(type == FTYPE_FILE)
                {
                    ret = -RED_EISDIR;
                }
            }
          #endif
            else
            {
                /*  Missing or unsupported inode type.
                */
                CRITICAL_ERROR();
                ret = -RED_EFUBAR;
            }
        }

      #if REDCONF_READ_ONLY == 0
        if((ret == 0) && fBranch)
        {
            ret = RedInodeBranch(pInode);
        }
      #endif

        if(ret != 0)
        {
            RedInodePut(pInode, 0U);
        }
    }

    return ret;
}
void Application::CreateTextures()
{
	D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc;
	descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
	descriptorHeapDesc.NumDescriptors = numTextures;
	descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
	descriptorHeapDesc.NodeMask = 1;
	if (FAILED(device->GetD3D12Device()->CreateDescriptorHeap(&descriptorHeapDesc, IID_PPV_ARGS(&textureDescriptorHeap))))
		CRITICAL_ERROR("Failed to create texture descriptor heap.");
	auto descriptorHandle = textureDescriptorHeap->GetCPUDescriptorHandleForHeapStart();


	// Would also be easy possible to place all textures into the same heap, but I do not see the advantes of that yet.

	const unsigned int textureSize = 16;
	char textureData[textureSize * textureSize * 4];

	// Texture desc, used by all textures
	D3D12_RESOURCE_DESC textureDesc = {};
	textureDesc.MipLevels = 1;
	textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	textureDesc.Width = textureSize;
	textureDesc.Height = textureSize;
	textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
	textureDesc.DepthOrArraySize = 1;
	textureDesc.SampleDesc.Count = 1;
	textureDesc.SampleDesc.Quality = 0;
	textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;


	ComPtr<ID3D12Resource> textureUploadHeap;
	D3D12_SUBRESOURCE_DATA subresourceData = {};
	subresourceData.pData = textureData;
	subresourceData.RowPitch = textureSize * 4;
	subresourceData.SlicePitch = subresourceData.RowPitch * textureSize;

	// Create the texture.
	for (unsigned int tex = 0; tex < numTextures; ++tex)
	{
		// Create texture
		if (FAILED(device->GetD3D12Device()->CreateCommittedResource(
			&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE,
			&textureDesc, D3D12_RESOURCE_STATE_COPY_DEST,
			nullptr, IID_PPV_ARGS(&textures[tex]))))
		{
			CRITICAL_ERROR("Failed to create texture");
		}

		// Create Upload buffer. Creating it outside the loop would make it impossible to use the GetRequiredIntermediateSize helper function
		if (tex == 0)
		{
			const UINT64 uploadBufferSize = GetRequiredIntermediateSize(textures[0].Get(), 0, 1);
			if (FAILED(device->GetD3D12Device()->CreateCommittedResource(
				&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
				D3D12_HEAP_FLAG_NONE,
				&CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
				D3D12_RESOURCE_STATE_GENERIC_READ, // D3D12_RESOURCE_STATE_GENERIC_READ is the only possible for D3D12_HEAP_TYPE_UPLOAD.
				nullptr,
				IID_PPV_ARGS(&textureUploadHeap))))
			{
				CRITICAL_ERROR("Failed to create upload heap for textures");
			}
		}


		// Create the GPU upload buffer.
		for (unsigned int j = 0; j < sizeof(textureData); ++j)
			textureData[j] = static_cast<unsigned char>(rand() % 255);

		// Copy over and wait until its done.
		commandList->Reset(commandAllocator[0].Get(), nullptr);
		//commandList->CopyResource(textures[i].Get(), textureUploadHeap.Get());
		UpdateSubresources(commandList.Get(), textures[tex].Get(), textureUploadHeap.Get(), 0, 0, 1, &subresourceData);
		commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(textures[tex].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
		commandList->Close();
		ID3D12CommandList* ppCommandLists[] = { commandList.Get() };
		device->GetDirectCommandQueue()->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
		device->WaitForIdleGPU();

		// Describe and create a SRV for the texture.
		D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
		srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
		srvDesc.Format = textureDesc.Format;
		srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
		srvDesc.Texture2D.MipLevels = 1;
		device->GetD3D12Device()->CreateShaderResourceView(textures[tex].Get(), &srvDesc, descriptorHandle);

		descriptorHandle.ptr += device->GetDescriptorSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
	}
}
void Application::CreatePSO()
{
	ComPtr<ID3DBlob> vertexShader, pixelShader;

#ifdef _DEBUG
	// Enable better shader debugging with the graphics debugging tools.
	UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#else
	UINT compileFlags = 0;
#endif

	ID3D10Blob* errorMessages;
	if (FAILED(D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, &errorMessages)))
	{
		if (errorMessages)
		{
			std::cout << static_cast<char*>(errorMessages->GetBufferPointer()) << std::endl;
			errorMessages->Release();
		}
		if (errorMessages)
			errorMessages->Release();

		CRITICAL_ERROR("Failed to compile vertex shader.");
	}
	if (FAILED(D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, &errorMessages)))
	{
		if (errorMessages)
		{
			std::cout << static_cast<char*>(errorMessages->GetBufferPointer()) << std::endl;
			errorMessages->Release();
		}
		if (errorMessages)
			errorMessages->Release();

		CRITICAL_ERROR("Failed to compile pixel shader.");
	}

	// Define the vertex input layout.
	D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
	};

	// Describe and create the graphics pipeline state object (PSO).
	D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
	psoDesc.pRootSignature = rootSignature.Get();
	psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), vertexShader->GetBufferSize() };
	psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), pixelShader->GetBufferSize() };
	psoDesc.DS;
	psoDesc.HS;
	psoDesc.GS;
	psoDesc.StreamOutput;
	psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
	psoDesc.SampleMask = UINT_MAX;
	psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
	psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
	psoDesc.DepthStencilState.DepthEnable = FALSE;
	psoDesc.DepthStencilState.StencilEnable = FALSE;
	psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };
	psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
	psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
	psoDesc.NumRenderTargets = 1;
	psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
	psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT;
	psoDesc.SampleDesc.Count = 1;
	psoDesc.CachedPSO;
	
	if(FAILED(device->GetD3D12Device()->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pso))))
		CRITICAL_ERROR("Failed to PSO.");
}
Пример #16
0
/** @brief Free an inode.

    @param pInode   Pointer to the cached inode structure.

    @return A negated ::REDSTATUS code indicating the operation result.

    @retval 0           Operation was successful.
    @retval -RED_EBADF  The inode is free.
    @retval -RED_EINVAL @p pInode is `NULL`; or pInode->pBuffer is `NULL`.
    @retval -RED_EIO    A disk I/O error occurred.
*/
REDSTATUS RedInodeFree(
    CINODE     *pInode)
{
    REDSTATUS   ret;

    if(!CINODE_IS_MOUNTED(pInode))
    {
        ret = -RED_EINVAL;
    }
    else
    {
        bool fSlot0Allocated;

        RedBufferDiscard(pInode->pInodeBuf);
        pInode->pInodeBuf = NULL;

        /*  Determine which of the two slots for the inode is currently
            allocated, and free that slot.
        */
        ret = RedInodeBitGet(gpRedCoreVol->bCurMR, pInode->ulInode, 0U, &fSlot0Allocated);

        if(ret == 0)
        {
            bool fSlot1Allocated;

            ret = RedInodeBitGet(gpRedCoreVol->bCurMR, pInode->ulInode, 1U, &fSlot1Allocated);

            if(ret == 0)
            {
                if(fSlot0Allocated)
                {
                    if(fSlot1Allocated)
                    {
                        /*  Both inode slots should never be allocated at
                            the same time.
                        */
                        CRITICAL_ERROR();
                        ret = -RED_EFUBAR;
                    }
                    else
                    {
                        ret = InodeBitSet(pInode->ulInode, 0U, false);
                    }
                }
                else
                {
                    if(!fSlot1Allocated)
                    {
                        /*  The inode in unallocated, which should have been
                            caught when it was mounted.
                        */
                        CRITICAL_ERROR();
                        ret = -RED_EBADF;
                    }
                    else
                    {
                        ret = InodeBitSet(pInode->ulInode, 1U, false);
                    }
                }
            }
        }

        pInode->ulInode = INODE_INVALID;

        if(ret == 0)
        {
            if(gpRedMR->ulFreeInodes >= gpRedVolConf->ulInodeCount)
            {
                CRITICAL_ERROR();
                ret = -RED_EFUBAR;
            }
            else
            {
                gpRedMR->ulFreeInodes++;
            }
        }
    }

    return ret;
}
Пример #17
0
/*  ½âÎöÊ¢´ó·ÀµÁÁ´ÅäÖÃÐÐ
 * sdo.download.ccgslb.net none 163music refere=idj.163.com  http://listen.idj.126.net/rj/rj.jsp 
 * */
int analysis163MusicCfg(struct redirect_conf *pstRedirectConf)
{
	char *pTemp;
	char *pcSep=" \t\r\n";
	ST_163MUSIC_CFG *pstC = NULL;
	char *cookie_next;
	char *cookie_ptr;
	int i = 0 ;
	
	pstC = (ST_163MUSIC_CFG*)malloc(sizeof(ST_163MUSIC_CFG));
	if(NULL == pstC)
	{
		CRITICAL_ERROR("No memory\n");
		goto error;
	}
	
	pTemp = xstrtok(NULL, pcSep);
	if(NULL == pTemp)
	{
		DEBUG("configure file is error,lack of cookie value");
		goto error;
	}

	while((cookie_ptr = strtok_r(pTemp,"|",&cookie_next))!=NULL) 
	{
		pstC->cookie_value[i] = strdup(cookie_ptr);
		DEBUG("pstC->cookie_value[%d] = %s\t ,cookie_next [%s]\n",i,pstC->cookie_value[i],cookie_next);
		i++;
		pTemp = NULL;
	}
	pstC->cookie_count = i--;
	for(i = 0; i <  pstC->cookie_count ; i ++)
		DEBUG("pstC->cookie_value[%d] = %s\n",i,pstC->cookie_value[i]);

	pTemp = xstrtok(NULL, pcSep);
	if(NULL == pTemp)
	{
		DEBUG("configure file is error,lack of replace url");
		goto error;
	}
	pstC->replace_url= strdup(pTemp);
	DEBUG("pstC->replace_url= %s\n", pstC->replace_url);

	pstRedirectConf->other = (void*)pstC;

	return 0;

error:
	if(NULL != pstC)
	{
		free(pstC);
	}

	for(i=0 ; i < pstC->cookie_count; i++)
	{
		if(NULL != pstC->cookie_value[i])
			free(pstC->cookie_value[i]);
		
	
	}
	if(NULL != pstC->replace_url)
		free(pstC->replace_url);

	return -1;

}