How to read subresource data in DirectX12? - directx-12

I have a DDS texture that I am creating using the CreateDDSTextureFromMemory12 function from the DDSTextureLoader helper library from microsoft. The texture has 10 mipmaps. I am able to create the texture and use it without any problem.
What I would like to do is read the texture data for a specific mipmap at a given index.
Here I am trying to read the data at the subresource index 5:
DirectX::CreateDDSTextureFromMemory12(
g_device,
g_cmd_list,
&bytes.front(),
file_size,
texResource,
tmpUploadHeap);
void* pData = nullptr;
texResource->ReadFromSubresource(pData, 64, 1, 5, nullptr);
However I am getting the following error:
D3D12 ERROR: ID3D12Resource1::ID3D12Resource::ReadFromSubresource:
ReadFromSubresource can not be called on a resource associated with a heap that has the CPU page properties of D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE.
Heaps of the type D3D12_HEAP_TYPE_DEFAULT should be assumed to have these properties.
[ RESOURCE_MANIPULATION ERROR #895: READFROMSUBRESOURCE_INVALIDRESOURCE]

The easiest way is to use LoadDDSTextureFromMemory from the DirectXTK12 project on github. The 5th parameter returns all the subresources in a std::vector.

Related

OpenGL: why does glMapNamedBuffer() return GL_INVALID_OPERATION?

Using OpenGL 4.6, I have the following (abbreviated) code, in which I create a buffer and then attempt to map it in order to copy data over using memcpy():
glCreateBuffers(buffers.size(), buffers.data()); // buffers is a std::array of GLuints
// ...
glNamedBufferStorage(buffers[3], n * sizeof(glm::vec4), nullptr, 0); // I also tried GL_DYNAMIC_STORAGE_BIT
// ...
void* bfrptr = glMapNamedBuffer(buffers[3], GL_WRITE_ONLY);
This latter call returns GL_INVALID_OPERATION. I am sure that this is the call that generates the error, as I catch OpenGL errors right before it as well. The manpage suggests that this error is only generated if the given buffer handle is not the name of an existing buffer object, but I'm sure I created it. Is there anything else I'm missing or that I'm doing wrong?
When you create immutable buffer storage, you must tell OpenGL how you intend to access that storage from the CPU. These are not "usage hints"; these are requirements, a contract between yourself and OpenGL which GL will hold you to.
You passed 0 for the access mask. That means that you told OpenGL (among other things) that you were not going to access it by mapping it. Which you then tried to do.
So it didn't let you.
If you want to map an immutable buffer, you must tell OpenGL at storage allocation time that you're going to do that. Specifically, if you want to map it for writing, you must use the GL_MAP_WRITE_BIT flag in the gl(Named)BufferStorage call.

Vulkan Image export handle to Win32 or fd. How to reverse win32 handle to obtain image information?

When I export a Win32 handle from the Vulkan image. Vulkan for another process. At this time, how to find the information of Vulkan Image according to win32 Handle reversely?
I created a Handle with Vulkan in a process and created OpenGL's texture according to the Handle. It is then shared with another process. So there is one of the above problems.
I don't know what the information of image is. How can I create an image and then import it into shared memory?
I don't know what the image information is, so how can I create an OpenGL texture object?
Therefore, I want to obtain the image information contained in Handle.
// Get the Vulkan texture and create the OpenGL equivalent using the memory allocated in Vulkan
inline void createTextureGL(nvvk::ResourceAllocator& alloc, Texture2DVkGL& texGl, int format, int minFilter, int magFilter, int wraps, int wrapt)
{
vk::Device device = alloc.getDevice();
nvvk::MemAllocator::MemInfo info = alloc.getMemoryAllocator()->getMemoryInfo(texGl.texVk.memHandle);
texGl.handle = device.getMemoryWin32HandleKHR({ info.memory, vk::ExternalMemoryHandleTypeFlagBits::eOpaqueWin32 });
auto req = device.getImageMemoryRequirements(texGl.texVk.image);
glCreateMemoryObjectsEXT(1, &texGl.memoryObject);
glImportMemoryWin32HandleEXT(texGl.memoryObject, req.size, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, texGl.handle);
glCreateTextures(GL_TEXTURE_2D, 1, &texGl.oglId);
glTextureStorageMem2DEXT(texGl.oglId, texGl.mipLevels, format, texGl.imgSize.width, texGl.imgSize.height, texGl.memoryObject, info.offset);
goolge-image-import project:
::VkImage image = *images_[0];
VkMemoryRequirements requirements;
device_->vkGetImageMemoryRequirements(device_, image, &requirements);
aligned_data_size_ =
vulkan::RoundUp(requirements.size, requirements.alignment);
uint32_t memory_index =
vulkan::GetMemoryIndex(&device, log, requirements.memoryTypeBits,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
#ifdef _WIN32
VkImportMemoryWin32HandleInfoKHR import_allocate_info{
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, handle, nullptr};
#elif __linux__
VkImportMemoryFdInfoKHR import_allocate_info{
VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, fd};
#endif
VkMemoryAllocateInfo allocate_info{
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
&import_allocate_info, // pNext
aligned_data_size_ * num_images, // allocationSize
memory_index};
VkDeviceMemory device_memory;
LOG_ASSERT(==, log, VK_SUCCESS,
device->vkAllocateMemory(device, &allocate_info, nullptr,
&device_memory));
I don't know what the information of image is.
Yes, you do. You created it in Vulkan. You know its size. You know its format. You know everything about the image.
If you can pass a handle to this function to create an OpenGL texture, then you can pass the other information too.
There is no API to retrieve any information about the window. The driver may not even be keeping such information around, since it's information you already have and is therefore redundant.

How to apply image effects to a JPEG in a memory buffer using LEADTOOLS 19

I'm making a Windows executable using C++, LEADTOOLS19, and VS2015 to read an image from a server, apply an image effect to it using LEADTOOLS, and display it in a browser.
The server provides me the image as an array of chars containing the JPEG encoding of the image (starting with "ÿØÿà") and the length of this buffer. Most of the LEADTOOLS functions read images from files, but I don't want to have to write it to disk just to read it as a bitmap.
The first thing I tried was the StartFeedLoad function:
//pImageData is the buffer of JPEG data, and imageLength is the
//server-provided size of pImageData in bytes
LBuffer buf((L_VOID *)pImageData, imageLength);
LFile imgFile;
LBitmap bitmap;
imgFile.SetBitmap(&imgbitmap);
// Initialize the file-load process
imgmemfile.StartFeedLoad(8, 0,
LOADFILE_ALLOCATE | LOADFILE_STORE, NULL);
imgmemfile.FeedLoad(&buf);
imgmemfile.StopFeedLoad();
With this code, I get this exception when trying to run StartFeedLoad:
Exception thrown at 0x000007F855BC2662 (ltwvcax.dll) in getimage.exe:
0xC0000005: Access violation reading location 0x0000000000000148.
I tried a few different things before calling StartFeedLoad, and tried changing the parameters I was passing it, but got that exception every time.
With that not working, the next method I tried was to save the buffer as an in-memory file using the LEADTOOLS library LMemoryFile class:
LBuffer buf((L_VOID *)pImageData, imageLength);
LMemoryFile imgmemfile;
BITMAPHANDLE pbit;
//The bitmap the image will be loaded into
LBitmap bitmap;
imgmemfile.SetBitmap(&bitmap);
//Load the buffer to the image
ret = imgmemfile.LoadMemory(buf, 0, ORDER_RGBORGRAY, LOADFILE_ALLOCATE | LOADFILE_STORE, NULL);
At this point, LoadMemory returns WRPERR_INVALID_PARAMETERS: One or more invalid parameters were specified. I've tried different bitsPerPixel values, color orders, and with or without adding another NULL parameter as fileInfo but still get the same error.
I feel like I need to do something else to "prep" the bitmap to load, but I don't know it's size or anything else to initialize it.
Thanks!
EDIT 5/9/16: Added "GetInfo" as indicated by Leadtools:
//Load image
LBuffer buf((L_VOID *)pImageData, imageLength);
//LFile imgmemfile;
FILEINFO fileInfo = FILEINFO();
LMemoryFile imgmemfile;
BITMAPHANDLE pbit;
if (LBase::GetLoadedLibraries() & LT_FIL == 0)
return false;
LBitmap bitmap;
imgmemfile.SetBitmap(&bitmap);
ret = imgmemfile.GetInfo(buf, &fileInfo, sizeof(FILEINFO), 0, NULL);
ret = imgmemfile.LoadMemory(buf, 0, ORDER_RGBORGRAY, LOADFILE_ALLOCATE | LOADFILE_STORE, NULL, &fileInfo);
ret = imgmemfile.Save(&buf, FILE_JPEG, 8, 30, NULL);
The code gets past the additional library check, but GetInfo returns -2041, indicating that LTFIL isn't loaded.
You should use LMemoryFile::GetInfo and LMemoryFile::LoadMemory if you have the whole file in memory at the start. If you don't, then FeedLoad is the way to go. There is an example here: https://www.leadtools.com/help/leadtools/v19/main/clib/lfile__startfeedload.html
You can find a full working example in your LEADTOOLS installation folder: C:\LEADTOOLS 19\Examples\ClassLibrary\MSVC\FeedLoad
The functions that LEADTOOLS Support gave me were correct, but I was still ahving the issue because I was linking to both the Unicode and ANSI versions of the Leadtools C++ class library (Ltwvc_x.lib AND Ltwvc_ax.lib). When I removed the Unicode library (from my ANSI project) everything worked fine.

Can't get CreateDDSTextureFromFile to work

So, I've been trying to figure out my problem for a few hours now, but I have no idea what I'm doing wrong. I'm a noob when it comes to DirectX programming, so I've been following some tutorials, and right now, I'm trying to create a obj loader.
http://www.braynzarsoft.net/index.php?p=D3D11OBJMODEL
However, I can't get my texture to work.
This is how I try to load the DDS-texture:
ID3D11ShaderResourceView* tempMeshSRV = nullptr;
hr = CreateDDSTextureFromFile(gDevice, L"boxTexture.dds", NULL, &tempMeshSRV);
if (SUCCEEDED(hr))
{
textureNameArray.push_back(L"boxTexture.dds");
material[matCount - 1].texArrayIndex = meshSRV.size();
meshSRV.push_back(tempMeshSRV);
material[matCount - 1].hasTexture = true;
}
However, my HRESULT will never Succeed, but it doesn't crash either. If I hoover over the hr, it just says "HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED) I also tried to remove the if statement, but that will just turn my box black.
Any idea on what I'm doing wrong? =/
Thanks in advance!
The most likely problem is that your "boxTexture.dds" is a 24 bit-per-pixel format file. In Direct3D 9, this was D3DFMT_R8G8B8 and was reasonably common. However, there is no DXGI equivalent format for 24 bits-per-pixel and it therefore requires format conversion to work.
The DDSTextureLoader module in DirectX Tool Kit is designed to be a minimum-overhead function, and therefore does no runtime conversions at all. If the data directly maps to a DXGI format, it loads. If it doesn't, it fails with HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED).
There are two different solutions depending on your usage scenario.
The ideal solution is to convert 'boxTexture.dds' to a supported format. You can do this with the texconv command-line tool provided with DirectXTex. This is by far the best option so that the potentially expensive conversion operation is done once and not very single time your application runs and loads the data.
If you don't actually control the source of the dds files you are trying load (i.e. they are arbitrary files provided by a user or you are doing some kind of content tool that has to support legacy formats), then you should make use of the DirectXTex 'full-fat' LoadFromDDSFile function which has extensive conversion code for handling legacy DDS file formats.
Note this situation can happen for a number of legacy format DDS files as list in the CodePlex wiki documentation
D3DFMT_R8G8B8 (24bpp RGB) - Use a 32bpp format
D3DFMT_X8B8G8R8 (32bpp RGBX) - Use BGRX, BGRA, or RGBA
D3DFMT_A2R10G10B10 (BGRA 10:10:10:2) - Use RGBA 10:10:10:2
D3DFMT_X1R5G5B5 (BGR 5:5:5) - Use BGRA 5:5:5:1 or BGR 5:6:5
D3DFMT_A8R3G3B2, D3DFMT_R3G3B2 (BGR 3:3:2) - Expand to a supported format
D3DFMT_P8, D3DFMT_A8P8 (8-bit palette) - Expand to a supported format
D3DFMT_A4L4 (Luminance 4:4) - Expand to a supported format
D3DFMT_UYVY (YUV 4:2:2 16bpp) - Swizzle to YUY2
See also Direct3D 11 Textures and Block Compression
If you look at the source code for CreateTextureFromDDS (which is called by CreateDDSTextureFromFile to do the main data processing) - http://directxtk.codeplex.com/SourceControl/latest#Src/DDSTextureLoader.cpp - you will see that there are a lot of reasons you could be getting "HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)".
It's not likely a problem with opening or reading the file since that would return a different error code. So most likely its an unsupported DXGI_FORMAT, a malformed cubemap, an invalid mipmap count, or invalid image dimensions (i.e. larger than the limits found here: http://msdn.microsoft.com/en-us/library/ff819065(v=vs.85).aspx ).

Writing ITK (insight Toolkit) results to local buffer

After applying an ITK filter pipeline, how do I write back the result to a buffer to be used (outside ITK)?
The Insight Software Guide has an example Book 1: Chapter 4.1.7: "Importing Image Data from a Buffer", and the same example is also found in the WikiExamples.
It shows how one can wrap a ITK pointer around a C++ array to use it further by using the ImportImageFilter object.
However, this example then uses a Writer object to write the filtered result to a file.
How do I write the filtered result into another C++ array instead? Or how do I overwrite the array I've used as input?
In essence, I've an application which contains an image in a buffer (localBuffer) which I can wrap following the example code:
[...]
const bool filterOwnsBuffer= false;
importFilter->SetImportPointer( localBuffer, size[0]*size[1], filterOwnsBuffer );
I can then use it it in any itk pipeline and 'update' it at a certain stage:
[...]
FilterType::Pointer filter = FilterType::New();
filter->SetInput( importFilter->GetOutput() );
filter->Update();
How do I now ensure that localbuffer has the filtered values? Or, alternatively, how do I set a different resultbuffer to the output values? Do I have to use the image iterator and 'loop' over my buffer manually? Or can I use the filter->GetOutput() more directly?
A little code example or a link to an according example would be very much appreciated.
(Simply the "Exporting Image Data to a Buffer" equivalent to the given import example.)
ImageType::Pointer output = filter->GetOutput();
ImageType::PixelContainer * outputContainer = output->GetPixelContainer();
ImageType::PixelContainer::Element * resultBuffer = outputContainer->GetBufferPointer();
See the Image documentation and ImportImageContainer documentation.
Here is the remedy for me:
memcpy( buffer, filter->GetOutput()->GetBufferPointer(),
size[0]*size[1]*sizeof(InputPixelType));
This works because by the time the filter is destroyed the buffer was already parsed to "buffer", which is the pointer to your data.