Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by leavittx · Dec 15, 2016 at 10:13 PM · renderingunity5texture2dnative plugindirectx 11

Directx12 CreateExternalTexture

Hi Unity developers and advanced users!

I'm working on a plugin which uses native rendering and needs to create a texture in C++ code, which then used inside Unity.

For DX11 i'm using ID3D11ShaderResourceView as a parameter for Texture2D.CreateExternalTexture(), however there is no documentation on what should be passed in DX12 case: https://docs.unity3d.com/ScriptReference/Texture2D.CreateExternalTexture.html

Here is my current C++ code:

 void* getTextureHandleForUnityDX12(ID3D12Resource* src_tex)
 {
       D3D12_RESOURCE_DESC src_tex_desc;
       src_tex_desc = src_tex->GetDesc();
 
       // Once the texture is created, we must create a shader resource view of it
       // so that shaders may use it.  In general, the view description will match
       // the texture description.
       D3D12_SHADER_RESOURCE_VIEW_DESC textureViewDesc;
       ZeroMemory(&textureViewDesc, sizeof(textureViewDesc));
       textureViewDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
       textureViewDesc.Format = src_tex_desc.Format;
       textureViewDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
       textureViewDesc.Texture2D.MipLevels = src_tex_desc.MipLevels;
       textureViewDesc.Texture2D.MostDetailedMip = 0;
 
       // create shader resource view and constant buffer view descriptor heap
       D3D12_DESCRIPTOR_HEAP_DESC descHeapCbvSrv = {};
       descHeapCbvSrv.NumDescriptors = 1;
       descHeapCbvSrv.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
       descHeapCbvSrv.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
 
       auto hr = m_device->CreateDescriptorHeap(
         &descHeapCbvSrv, __uuidof(ID3D12DescriptorHeap), (void**)&m_descriptorHeap);
       if (FAILED(hr)) { return TranslateReturnCode(hr); }
 
       // https://software.intel.com/en-us/articles/introduction-to-resource-binding-in-microsoft-directx-12
       CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle0(m_descriptorHeap->GetCPUDescriptorHandleForHeapStart());
       m_device->CreateShaderResourceView(src_tex, &textureViewDesc, srvHandle0);
 
       // Doesn't work: the texture in Unity remains black
       return (void*)&srvHandle0;
 }

Maybe you could add an example of that to https://bitbucket.org/Unity-Technologies/graphicsdemos as well, I think some people will find it quite useful.

Thanks, Lev

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by Baroque · Jan 07, 2017 at 05:31 PM

In the native rendering plugin example it's not immediately obvious what type to use but if you dig into the implementation of RenderAPI_D3D12 you'll see the following bit of code in EndModifyTexture:

 void RenderAPI_D3D12::EndModifyTexture(void* textureHandle, int textureWidth, int textureHeight, int rowPitch, void* dataPtr)
 {
     ID3D12Device* device = s_D3D12->GetDevice();

     const UINT64 kDataSize = textureWidth * textureHeight * 4;
     ID3D12Resource* upload = GetUploadResource(kDataSize);
     upload->Unmap(0, NULL);

     ID3D12Resource* resource = (ID3D12Resource*)textureHandle;
     D3D12_RESOURCE_DESC desc = resource->GetDesc();
     assert(desc.Width == textureWidth);
     assert(desc.Height == textureHeight);

You can see textureHandle is cast to ID3D12Resource. That's what Unity will return if you call GetNativePtr on a Texture2D in DirectX12, so that's what you should use to create a Unity texture from scratch.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by leavittx · Jan 29, 2017 at 07:43 PM

Hey. I tried passing ID3D12Resource* to Texture2D.CreateExternalTexture(), but it didn't work at all.

I will post my createTexture2D() method code:

 Result createTexture2D(void **dst_tex, int width, int height, TextureFormat format, ResourceFlags flags)
   {
       D3D12_HEAP_PROPERTIES heap  = {};
       heap.Type                   = D3D12_HEAP_TYPE_DEFAULT;
       heap.CPUPageProperty        = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
       heap.MemoryPoolPreference   = D3D12_MEMORY_POOL_UNKNOWN;
       heap.CreationNodeMask       = 1;
       heap.VisibleNodeMask        = 1;
 
       D3D12_RESOURCE_DESC desc = {};
       desc.Dimension          = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
       desc.Alignment          = 0;
       desc.Width              = (UINT64)width;
       desc.Height             = (UINT)height;
       desc.DepthOrArraySize   = 1;
       desc.MipLevels          = 1;
       desc.Format             = GetDXGIFormat(format);
       desc.SampleDesc.Count   = 1;
       desc.SampleDesc.Quality = 0;
       desc.Layout             = D3D12_TEXTURE_LAYOUT_UNKNOWN;
       desc.Flags              = D3D12_RESOURCE_FLAG_NONE;
 
       // texture can't be created with D3D12_HEAP_TYPE_UPLOAD / D3D12_HEAP_TYPE_READBACK heap type.
       // ResourceFlags::CPU_Write / CPU_Read flag is ignored.
 
       ID3D12Resource *tex = nullptr;
       auto hr = m_device->CreateCommittedResource(&heap, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&tex) );
       if ( FAILED( hr ) ) { return TranslateReturnCode(hr); }
       *dst_tex = tex;
 
       return Result::OK;
   }


Along with writeTexture2D() code:

 Result writeTexture2D(void *dst_tex_, int width, int height, TextureFormat format, const void *src, size_t write_size)
   {
       if (write_size == 0) { return Result::OK; }
       if (!dst_tex_ || !src) { return Result::InvalidParameter; }
 
       auto *dst_tex = (ID3D12Resource*)dst_tex_;
 
       D3D12_RESOURCE_DESC dst_desc = dst_tex->GetDesc();
       D3D12_PLACED_SUBRESOURCE_FOOTPRINT dst_layout;
       UINT dst_num_rows;
       UINT64 dst_row_size;
       UINT64 dst_required_size;
       m_device->GetCopyableFootprints(&dst_desc, 0, 1, 0, &dst_layout, &dst_num_rows, &dst_row_size, &dst_required_size);
 
 
       auto write_proc = [](ID3D12Resource *dst_tex, int width, int height, TextureFormat format, const void *src, size_t write_size, D3D12_PLACED_SUBRESOURCE_FOOTPRINT& dst_layout) {
           void *mapped_data = nullptr;
           auto hr = dst_tex->Map(0, nullptr, &mapped_data);
           if (FAILED(hr)) { return hr; }
 
           int dst_pitch = dst_layout.Footprint.RowPitch;
           int src_pitch = width * GetTexelSize(format);
 
           int num_rows = std::min<int>(std::min<int>(height, dst_layout.Footprint.Height),
                                        ceildiv<size_t>(write_size, src_pitch));
         
           CopyRegion(mapped_data, dst_pitch, src, src_pitch, num_rows);
           dst_tex->Unmap(0, nullptr);
           return S_OK;
       };
 
 
       // try direct access
       auto hr = write_proc(dst_tex, width, height, format, src, write_size, dst_layout);
       if (SUCCEEDED(hr)) { return Result::OK; }
 
 
       // try copy-via-staging
       auto staging = createStagingBuffer(dst_required_size, StagingFlag::Upload);
       if (!staging) { return Result::OutOfMemory; }
 
       hr = write_proc(staging.Get(), width, height, format, src, write_size, dst_layout);
       if (FAILED(hr)) { return TranslateReturnCode(hr); }
 
       hr = executeCommands([&](ID3D12GraphicsCommandList *clist) {
           CD3DX12_TEXTURE_COPY_LOCATION dst_region(dst_tex, 0);
           CD3DX12_TEXTURE_COPY_LOCATION src_region(staging.Get(), dst_layout);
 
           clist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(dst_tex, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));
           clist->CopyTextureRegion(&dst_region, 0, 0, 0, &src_region, nullptr);
           clist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(dst_tex, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COMMON));
       });
       if (FAILED(hr)) { return TranslateReturnCode(hr); }
 
       return Result::OK;
   }

Maybe someone can point me to possible problems with this code.

One good thing is that now I can see that the writeTexture2D() code is rather a DX11 copy-paste with some changes applied to make it compile with DX12 API being used, then a DX12-oriented solution. Should I try something with GetUploadResource() like GraphicsDemos does ?

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Update DX11 texture asynchronously in native plugin? 2 Answers

Native Rendering Plugin with Oculus Rift 0 Answers

Texture appears Pink on Device (works on editor) 3 Answers

glTexSubImage3D in unity 0 Answers

How do I insert custom rendering before transparent objects? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges