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()); }
// ------------------------------------------------------------------------- // // 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"); }
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); }
/** @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."); }
/** @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; }
/** @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; }
/** @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; }
/** @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; }
/** @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; }
/** @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."); }
/** @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; }
/* ½âÎöÊ¢´ó·ÀµÁÁ´ÅäÖÃÐÐ * 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; }