Result GraphicsInterfaceD3D11::createTexture2D(void **dst_tex, int width, int height, TextureFormat format, const void *data, ResourceFlags flags) { size_t texel_size = GetTexelSize(format); DXGI_FORMAT internal_format = GetDXGIFormat(format); D3D11_TEXTURE2D_DESC desc = { (UINT)width, (UINT)height, 1, 1, internal_format, { 1, 0 }, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0 }; if (flags & ResourceFlags::CPU_Write) { desc.Usage = D3D11_USAGE_DYNAMIC; desc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE; } if (flags & ResourceFlags::CPU_Read) { desc.Usage = D3D11_USAGE_STAGING; desc.CPUAccessFlags |= D3D11_CPU_ACCESS_READ; desc.BindFlags = 0; } D3D11_SUBRESOURCE_DATA subr = { data, width * (UINT)texel_size, width * height * (UINT)texel_size, }; ID3D11Texture2D *ret = nullptr; HRESULT hr = m_device->CreateTexture2D(&desc, data ? &subr : nullptr, &ret); if (FAILED(hr)) { return TranslateReturnCode(hr); } *dst_tex = ret; return Result::OK; }
DDSRESULT dds_load_info( dds_info* out, size_t size, DDS_HEADER* hdr, DDS_HEADER_DXT10* hdr10 ) { static const dds_u32 sideflags[6] = { DDS_CUBEMAP_PX, DDS_CUBEMAP_NX, DDS_CUBEMAP_PY, DDS_CUBEMAP_NY, DDS_CUBEMAP_PZ, DDS_CUBEMAP_NZ }; int i; dds_u32 sum, sum2; dds_image_info plane; out->image.width = hdr->width; out->image.height = hdr->height; out->image.depth = hdr->flags & DDSD_DEPTH ? hdr->depth : 1; out->image.format = dds_supported_format( GetDXGIFormat( hdr->ddspf ) ); out->mipcount = hdr->flags & DDSD_MIPMAPCOUNT ? hdr->mipMapCount : 1; out->flags = 0; if( hdr->caps2 & DDSCAPS2_VOLUME ) out->flags |= DDS_VOLUME; if( hdr->caps2 & DDSCAPS2_CUBEMAP ) out->flags |= DDS_CUBEMAP; if( hdr->caps2 & DDSCAPS2_CUBEMAP_POSITIVEX ) out->flags |= DDS_CUBEMAP_PX; if( hdr->caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX ) out->flags |= DDS_CUBEMAP_NX; if( hdr->caps2 & DDSCAPS2_CUBEMAP_POSITIVEY ) out->flags |= DDS_CUBEMAP_PY; if( hdr->caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY ) out->flags |= DDS_CUBEMAP_NY; if( hdr->caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ ) out->flags |= DDS_CUBEMAP_PZ; if( hdr->caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ ) out->flags |= DDS_CUBEMAP_NZ; if( out->mipcount > 16 ) return DDS_ENOTSUP; sum = 0; for( i = 0; i < out->mipcount; ++i ) { out->mipoffsets[ i ] = sum; out->mip = i; dds_getinfo( out, &plane ); sum += plane.size; } sum2 = 0; for( i = 0; i < 6; ++i ) { out->sideoffsets[ i ] = sum2; if( out->flags & DDS_CUBEMAP && out->flags & sideflags[ i ] ) sum2 += sum; } out->image.size = out->flags & DDS_CUBEMAP ? sum2 : sum; out->data = NULL; out->side = 0; out->mip = 0; printf( "loaded dds: w=%d h=%d d=%d fmt=%d mips=%d cube=%s size=%d\n", (int) out->image.width, (int) out->image.height, (int) out->image.depth, (int) out->image.format, (int) out->mipcount, out->flags & DDS_CUBEMAP ? "true" : "false", (int) out->image.size ); return DDS_SUCCESS; }
void ProceduralTexture::Create(const void* data, uint32_t width, uint32_t height, Format format, uint32_t bpp) { Assert(!resource_ && data); width_ = width; height_ = height; depth_ = 1; format_ = format; DXGI_FORMAT dxgiFormat = GetDXGIFormat(format); // テクスチャ生成 D3D11_TEXTURE2D_DESC objdesc; ZeroMemory(&objdesc, sizeof(objdesc)); objdesc.Width = width; objdesc.Height = height; objdesc.MipLevels = 1; objdesc.ArraySize = 1; objdesc.SampleDesc.Count = 1; objdesc.SampleDesc.Quality = 0; objdesc.MiscFlags = 0; objdesc.Format = dxgiFormat; objdesc.Usage = D3D11_USAGE_DEFAULT; objdesc.CPUAccessFlags = 0; objdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; D3D11_SUBRESOURCE_DATA dataBin; dataBin.pSysMem = data; dataBin.SysMemPitch = bpp * width; dataBin.SysMemSlicePitch = 0; // テクスチャ生成 auto* device = GraphicsCore::GetDevice(); ID3D11Texture2D* texture; THROW_IF_FAILED(device->CreateTexture2D(&objdesc, &dataBin, &texture)); resource_ = texture; // シェーダリソースビュー D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; memset(&srvDesc, 0, sizeof(srvDesc)); srvDesc.Format = dxgiFormat; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = 1; THROW_IF_FAILED(device->CreateShaderResourceView(texture, &srvDesc, &srv_)); }
/** If different input slot classes are needed, the caller of this function is responsible for that. **/ void ShaderInfo::CreateInputLayout(D3D11_INPUT_ELEMENT_DESC* layout, UINT elementCount, bool perVertex /*= true */, UINT instanceDataStepRate /* = 0 */) { for(UINT i = 0; i < elementCount; i++) { layout[i].SemanticName = m_inputParams[i].SemanticName; layout[i].SemanticIndex = m_inputParams[i].SemanticIndex; layout[i].Format = GetDXGIFormat(m_inputParams[i]); layout[i].InputSlot = 0; layout[i].InstanceDataStepRate = instanceDataStepRate; if(perVertex) layout[i].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; else layout[i].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;; if(i == 0) layout[i].AlignedByteOffset = 0; else layout[i].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; } }
ComPtr<ID3D11Texture2D> GraphicsInterfaceD3D11::createStagingTexture(int width, int height, TextureFormat format, StagingFlag flag) { D3D11_TEXTURE2D_DESC desc = {}; desc.Width = (UINT)width; desc.Height = (UINT)height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = GetDXGIFormat(format); desc.SampleDesc = { 1, 0 }; desc.Usage = D3D11_USAGE_STAGING; if (flag == StagingFlag::Upload) { desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; } if (flag == StagingFlag::Readback) { desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; } auto ret = ComPtr<ID3D11Texture2D>(); auto hr = m_device->CreateTexture2D(&desc, nullptr, &ret); return ret; }
//-------------------------------------------------------------------------- VeBlobPtr ParseDDS(VeTexture::FileInfo& kOut, VeMemoryIStream& kIn) noexcept { if (kIn.RemainingLength() < sizeof(DDS_HEADER)) return nullptr; DDS_HEADER* pkHeader = kIn.To<DDS_HEADER>(); if (pkHeader->m_u32Size != sizeof(DDS_HEADER) || pkHeader->m_kFormat.m_u32Size != sizeof(DDS_PIXELFORMAT)) return nullptr; DDS_HEADER_DXT10* pkHeader10 = nullptr; if ((pkHeader->m_kFormat.m_u32Flags & DDS_FOURCC) && (VE_FOURCC('D', 'X', '1', '0') == pkHeader->m_kFormat.m_u32FourCC)) { if (kIn.RemainingLength() < sizeof(DDS_HEADER_DXT10)) return nullptr; pkHeader10 = kIn.To<DDS_HEADER_DXT10>(); } VeUInt32 u32Width = pkHeader->m_u32Width; VeUInt32 u32Height = pkHeader->m_u32Height; VeUInt32 u32Depth = pkHeader->m_u32Depth; VeRenderResource::Dimension eResDim = VeRenderResource::DIMENSION_UNKNOWN; VeUInt32 u32ArraySize = 1; VeRenderResource::Format eFormat = VeRenderResource::FORMAT_UNKNOWN; bool bIsCubeMap = false; VeUInt32 u32MipCount = pkHeader->m_u32MipMapCount ? pkHeader->m_u32MipMapCount : 1; if (pkHeader10) { u32ArraySize = pkHeader10->m_u32ArraySize; if (u32ArraySize == 0) return nullptr; switch (pkHeader10->m_eFormat) { case VeRenderResource::FORMAT_AI44: case VeRenderResource::FORMAT_IA44: case VeRenderResource::FORMAT_P8: case VeRenderResource::FORMAT_A8P8: return nullptr; default: if (VeRenderResource::BitsPerPixel(pkHeader10->m_eFormat) == 0) { return nullptr; } } eFormat = pkHeader10->m_eFormat; switch (pkHeader10->m_eResourceDimension) { case VeRenderResource::DIMENSION_TEXTURE1D: if ((pkHeader->m_u32Flags & DDS_HEIGHT) && u32Height != 1) { return nullptr; } u32Height = u32Depth = 1; break; case VeRenderResource::DIMENSION_TEXTURE2D: if (pkHeader10->m_u32MiscFlag & RESOURCE_MISC_TEXTURECUBE) { u32ArraySize *= 6; bIsCubeMap = true; } u32Depth = 1; break; case VeRenderResource::DIMENSION_TEXTURE3D: if (!(pkHeader->m_u32Flags & DDS_HEADER_FLAGS_VOLUME)) { return nullptr; } if (u32ArraySize > 1) { return nullptr; } break; default: return nullptr; } eResDim = pkHeader10->m_eResourceDimension; } else { eFormat = GetDXGIFormat(pkHeader->m_kFormat); if (eFormat == VeRenderResource::FORMAT_UNKNOWN) { return nullptr; } if (pkHeader->m_u32Flags & DDS_HEADER_FLAGS_VOLUME) { eResDim = VeRenderResource::DIMENSION_TEXTURE3D; } else { if (pkHeader->m_u32Caps2 & DDS_CUBEMAP) { if ((pkHeader->m_u32Caps2 & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES) { return nullptr; } u32ArraySize = 6; bIsCubeMap = true; } u32Depth = 1; eResDim = VeRenderResource::DIMENSION_TEXTURE2D; } VE_ASSERT(VeRenderResource::BitsPerPixel(eFormat) != 0); } if (u32MipCount > REQ_MIP_LEVELS) { return nullptr; } switch (eResDim) { case VeRenderResource::DIMENSION_TEXTURE1D: if ((u32ArraySize > REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION) || (u32Width > REQ_TEXTURE1D_U_DIMENSION)) { return nullptr; } break; case VeRenderResource::DIMENSION_TEXTURE2D: if (bIsCubeMap) { if ((u32ArraySize > REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) || (u32Width > REQ_TEXTURECUBE_DIMENSION) || (u32Height > REQ_TEXTURECUBE_DIMENSION)) { return nullptr; } } else if ((u32ArraySize > REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION) || (u32Width > REQ_TEXTURE2D_U_OR_V_DIMENSION) || (u32Height > REQ_TEXTURE2D_U_OR_V_DIMENSION)) { return nullptr; } break; case VeRenderResource::DIMENSION_TEXTURE3D: if ((u32ArraySize > 1) || (u32Width > REQ_TEXTURE3D_U_V_OR_W_DIMENSION) || (u32Height > REQ_TEXTURE3D_U_V_OR_W_DIMENSION) || (u32Depth > REQ_TEXTURE3D_U_V_OR_W_DIMENSION)) { return nullptr; } break; default: return nullptr; } if (u32Depth != 1 && u32ArraySize != 1) return nullptr; kOut.m_eDimension = eResDim; kOut.m_eFormat = eFormat; kOut.m_u32Width = u32Width; kOut.m_u32Height = u32Height; kOut.m_u16Depth = (VeUInt16)(u32Depth * u32ArraySize); kOut.m_u16MipLevels = (VeUInt16)u32MipCount; kOut.m_bIsCube = bIsCubeMap; VeSizeT stDataSize = kIn.RemainingLength(); void* pvData = kIn.Skip(stDataSize); return VE_NEW VeBlob(pvData, stDataSize); }
//-------------------------------------------------------------------------------------- static HRESULT CreateTextureFromDDS( ID3D10Device* pDev, DDS_HEADER* pHeader, BYTE* pBitData, UINT BitSize, ID3D10ShaderResourceView** ppSRV, bool bSRGB ) { HRESULT hr = S_OK; UINT iWidth = pHeader->dwWidth; UINT iHeight = pHeader->dwHeight; UINT iMipCount = pHeader->dwMipMapCount; if( 0 == iMipCount ) iMipCount = 1; D3D10_TEXTURE2D_DESC desc; if (( pHeader->ddspf.dwFlags & DDS_FOURCC ) && (MAKEFOURCC( 'D', 'X', '1', '0' ) == pHeader->ddspf.dwFourCC ) ) { DDS_HEADER_DXT10* d3d10ext = (DDS_HEADER_DXT10*)( (char*)pHeader + sizeof(DDS_HEADER) ); desc.ArraySize = d3d10ext->arraySize; desc.Format = d3d10ext->dxgiFormat; // For now, we only support 2D textures if ( d3d10ext->resourceDimension != D3D10_RESOURCE_DIMENSION_TEXTURE2D ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } else { desc.ArraySize = 1; desc.Format = GetDXGIFormat( pHeader->ddspf ); if (pHeader->dwCubemapFlags != 0 || (pHeader->dwHeaderFlags & DDS_HEADER_FLAGS_VOLUME) ) { // For now only support 2D textures, not cubemaps or volumes return E_FAIL; } if( desc.Format == DXGI_FORMAT_UNKNOWN ) { D3DFORMAT fmt = GetD3D9Format( pHeader->ddspf ); // Swizzle some RGB to BGR common formats to be DXGI (1.0) supported switch( fmt ) { case D3DFMT_X8R8G8B8: case D3DFMT_A8R8G8B8: { desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; for( UINT i = 0; i < BitSize; i += 4 ) { BYTE a = pBitData[i]; pBitData[i] = pBitData[i + 2]; pBitData[i + 2] = a; } } break; // Need more room to try to swizzle 24bpp or 4bpp formats default: return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } } } if ( bSRGB ) desc.Format = MAKE_SRGB( desc.Format ); // Create the texture desc.Width = iWidth; desc.Height = iHeight; desc.MipLevels = iMipCount; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D10_USAGE_DEFAULT; desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; ID3D10Texture2D* pTex2D; D3D10_SUBRESOURCE_DATA* pInitData = new D3D10_SUBRESOURCE_DATA[iMipCount]; if( !pInitData ) return E_OUTOFMEMORY; UINT NumBytes = 0; UINT RowBytes = 0; UINT NumRows = 0; BYTE* pSrcBits = pBitData; for( UINT j = 0; j < desc.ArraySize; j++ ) { for( UINT i = 0; i < iMipCount; i++ ) { GetSurfaceInfo( iWidth, iHeight, desc.Format, &NumBytes, &RowBytes, &NumRows ); pInitData[i].pSysMem = ( void* )pSrcBits; pInitData[i].SysMemPitch = RowBytes; pSrcBits += NumBytes; iWidth = iWidth >> 1; iHeight = iHeight >> 1; if( iWidth == 0 ) iWidth = 1; if( iHeight == 0 ) iHeight = 1; } } hr = pDev->CreateTexture2D( &desc, pInitData, &pTex2D ); if( SUCCEEDED( hr ) && pTex2D ) { D3D10_SHADER_RESOURCE_VIEW_DESC SRVDesc; ZeroMemory( &SRVDesc, sizeof( SRVDesc ) ); SRVDesc.Format = desc.Format; SRVDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = desc.MipLevels; hr = pDev->CreateShaderResourceView( pTex2D, &SRVDesc, ppSRV ); SAFE_RELEASE( pTex2D ); } SAFE_DELETE( pInitData ); return hr; }
void ColorBuffer::Create2D(Format format, uint32_t width, uint32_t height, uint32_t arraySize, uint32_t mips, bool unorderedAccess) { Assert(!resource_); mips = se::Max<uint32_t>(1, mips); width_ = width; height_ = height; depth_ = arraySize; format_ = format; DXGI_FORMAT dxgiFormat = GetDXGIFormat(format); // テクスチャ生成 D3D11_TEXTURE2D_DESC objdesc; ZeroMemory(&objdesc, sizeof(objdesc)); objdesc.Width = width; objdesc.Height = height; objdesc.MipLevels = mips; objdesc.ArraySize = arraySize; objdesc.SampleDesc.Count = 1; objdesc.SampleDesc.Quality = 0; objdesc.MiscFlags = 0; objdesc.Format = dxgiFormat; objdesc.Usage = D3D11_USAGE_DEFAULT; objdesc.CPUAccessFlags = 0; objdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; if(unorderedAccess) objdesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; // テクスチャ生成 auto* device = GraphicsCore::GetDevice(); ID3D11Texture2D* texture; THROW_IF_FAILED(device->CreateTexture2D(&objdesc, nullptr, &texture)); resource_ = texture; // シェーダリソースビュー bool isArray = (arraySize > 1); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; memset(&srvDesc, 0, sizeof(srvDesc)); srvDesc.Format = dxgiFormat; if (isArray) { srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.ArraySize = arraySize; srvDesc.Texture2DArray.MipLevels = mips; } else { srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = mips; } THROW_IF_FAILED(device->CreateShaderResourceView(texture, &srvDesc, &srv_)); // レンダーターゲットビュー D3D11_RENDER_TARGET_VIEW_DESC rdesc; rdesc.Format = dxgiFormat; rdesc.ViewDimension = (arraySize > 1 || mips > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DARRAY : D3D11_RTV_DIMENSION_TEXTURE2D; rdesc.Texture2DArray.ArraySize = 1; rdesc.Texture2DArray.MipSlice = 0; rdesc.Texture2DArray.FirstArraySlice = 0; THROW_IF_FAILED(device->CreateRenderTargetView(texture, &rdesc, &rtv_)); // アンオーダードアクセスビューを生成 if (unorderedAccess) { D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; if (isArray) { uavDesc.Texture2DArray.ArraySize = arraySize; uavDesc.Texture2DArray.FirstArraySlice = 0; uavDesc.Texture2DArray.MipSlice = 0; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; } else { uavDesc.Texture2D.MipSlice = 0; uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; } uavDesc.Format = dxgiFormat; THROW_IF_FAILED(GraphicsCore::GetDevice()->CreateUnorderedAccessView(resource_, &uavDesc, &uav_)); } }