mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-09 08:41:31 +00:00
[idd] capture: preserve software copy row pitch
Use an explicit placed buffer for software frame copies so the D3D copy uses the same row pitch published through KVMFR. GetCopyableFootprints describes buffer copies and cannot be used to infer the physical layout of a placed row-major texture. This caused padded resolutions to use the wrong row starts in every consumer. Keep the copy direct to IVSHMEM without a staging or CPU copy.
This commit is contained in:
@@ -37,16 +37,14 @@ void CFrameBufferPool::Reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
CFrameBufferResource * CFrameBufferPool::Get(
|
CFrameBufferResource * CFrameBufferPool::Get(
|
||||||
const PreparedFrameBuffer& buffer,
|
const PreparedFrameBuffer& buffer, size_t minSize)
|
||||||
size_t minSize, const D3D12_RESOURCE_DESC * textureDesc)
|
|
||||||
{
|
{
|
||||||
if (buffer.frameIndex > ARRAYSIZE(m_buffers) - 1)
|
if (buffer.frameIndex > ARRAYSIZE(m_buffers) - 1)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
CFrameBufferResource * fbr = &m_buffers[buffer.frameIndex];
|
CFrameBufferResource * fbr = &m_buffers[buffer.frameIndex];
|
||||||
if (!fbr->Init(m_dx12, buffer.frameIndex, buffer.mem,
|
if (!fbr->Init(m_dx12, buffer.frameIndex, buffer.mem,
|
||||||
buffer.heapOffset, minSize, m_transport->GetMaxFrameSize(),
|
buffer.heapOffset, minSize, m_transport->GetMaxFrameSize()))
|
||||||
textureDesc))
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return fbr;
|
return fbr;
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ public:
|
|||||||
void Init(IFrameTransport * transport, CD3D12Device * dx12);
|
void Init(IFrameTransport * transport, CD3D12Device * dx12);
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
CFrameBufferResource * Get(const PreparedFrameBuffer& buffer,
|
CFrameBufferResource * Get(
|
||||||
size_t minSize,
|
const PreparedFrameBuffer& buffer, size_t minSize);
|
||||||
const D3D12_RESOURCE_DESC * textureDesc = nullptr);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "capture/CFrameBufferResource.h"
|
#include "capture/CFrameBufferResource.h"
|
||||||
#include "capture/CFrameProcessorUtil.h"
|
|
||||||
#include "d3d/CD3D12Device.h"
|
#include "d3d/CD3D12Device.h"
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
|
||||||
@@ -27,7 +26,7 @@
|
|||||||
|
|
||||||
bool CFrameBufferResource::Init(CD3D12Device * dx12,
|
bool CFrameBufferResource::Init(CD3D12Device * dx12,
|
||||||
unsigned frameIndex, uint8_t * base, uint64_t heapOffset, size_t size,
|
unsigned frameIndex, uint8_t * base, uint64_t heapOffset, size_t size,
|
||||||
size_t maxFrameSize, const D3D12_RESOURCE_DESC * textureDesc)
|
size_t maxFrameSize)
|
||||||
{
|
{
|
||||||
m_frameIndex = frameIndex;
|
m_frameIndex = frameIndex;
|
||||||
|
|
||||||
@@ -38,52 +37,27 @@ bool CFrameBufferResource::Init(CD3D12Device * dx12,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool indirect = dx12->IsIndirectCopy();
|
const bool indirect = dx12->IsIndirectCopy();
|
||||||
const ResourceType type = textureDesc ?
|
|
||||||
RESOURCE_TEXTURE : RESOURCE_BUFFER;
|
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC desc = {};
|
D3D12_RESOURCE_DESC desc = {};
|
||||||
if (textureDesc)
|
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||||
|
desc.Width = size;
|
||||||
|
desc.Height = 1;
|
||||||
|
desc.DepthOrArraySize = 1;
|
||||||
|
desc.MipLevels = 1;
|
||||||
|
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.SampleDesc.Quality = 0;
|
||||||
|
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||||
|
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
if (!indirect)
|
||||||
{
|
{
|
||||||
if (indirect || !dx12->CanUseDirectTexture())
|
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
||||||
return false;
|
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER;
|
||||||
desc = *textureDesc;
|
|
||||||
if (desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D ||
|
|
||||||
!desc.Width ||
|
|
||||||
!desc.Height ||
|
|
||||||
desc.DepthOrArraySize != 1 ||
|
|
||||||
desc.MipLevels != 1 ||
|
|
||||||
desc.SampleDesc.Count != 1 ||
|
|
||||||
desc.SampleDesc.Quality ||
|
|
||||||
desc.Format == DXGI_FORMAT_UNKNOWN ||
|
|
||||||
desc.Layout != D3D12_TEXTURE_LAYOUT_ROW_MAJOR ||
|
|
||||||
desc.Flags != D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
|
||||||
desc.Width = size;
|
|
||||||
desc.Height = 1;
|
|
||||||
desc.DepthOrArraySize = 1;
|
|
||||||
desc.MipLevels = 1;
|
|
||||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
|
||||||
desc.SampleDesc.Count = 1;
|
|
||||||
desc.SampleDesc.Quality = 0;
|
|
||||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
||||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
|
||||||
if (!indirect)
|
|
||||||
{
|
|
||||||
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
|
||||||
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing to do if the resource already represents this allocation.
|
// Nothing to do if the resource already represents this allocation.
|
||||||
if (m_base == base && m_type == type &&
|
if (m_base == base && m_size >= size)
|
||||||
((type == RESOURCE_BUFFER && m_size >= size) ||
|
|
||||||
(type == RESOURCE_TEXTURE &&
|
|
||||||
CFrameProcessorUtil::ResourceDescMatches(m_desc, desc))))
|
|
||||||
{
|
{
|
||||||
m_frameSize = size;
|
m_frameSize = size;
|
||||||
return true;
|
return true;
|
||||||
@@ -93,7 +67,6 @@ bool CFrameBufferResource::Init(CD3D12Device * dx12,
|
|||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
const WCHAR * resName;
|
const WCHAR * resName;
|
||||||
UINT64 allocationSize = size;
|
|
||||||
|
|
||||||
if (indirect)
|
if (indirect)
|
||||||
{
|
{
|
||||||
@@ -130,7 +103,6 @@ bool CFrameBufferResource::Init(CD3D12Device * dx12,
|
|||||||
{
|
{
|
||||||
const D3D12_RESOURCE_ALLOCATION_INFO allocation =
|
const D3D12_RESOURCE_ALLOCATION_INFO allocation =
|
||||||
dx12->GetDevice()->GetResourceAllocationInfo(0, 1, &desc);
|
dx12->GetDevice()->GetResourceAllocationInfo(0, 1, &desc);
|
||||||
allocationSize = allocation.SizeInBytes;
|
|
||||||
const D3D12_HEAP_DESC heapDesc =
|
const D3D12_HEAP_DESC heapDesc =
|
||||||
dx12->GetTransportHeap()->GetDesc();
|
dx12->GetTransportHeap()->GetDesc();
|
||||||
if (!allocation.Alignment ||
|
if (!allocation.Alignment ||
|
||||||
@@ -144,26 +116,8 @@ bool CFrameBufferResource::Init(CD3D12Device * dx12,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == RESOURCE_TEXTURE)
|
DEBUG_TRACE("Creating transport buffer for %p", base);
|
||||||
{
|
resName = L"Transport Buffer";
|
||||||
D3D12_FEATURE_DATA_FORMAT_SUPPORT support = {};
|
|
||||||
support.Format = desc.Format;
|
|
||||||
hr = dx12->GetDevice()->CheckFeatureSupport(
|
|
||||||
D3D12_FEATURE_FORMAT_SUPPORT, &support, sizeof(support));
|
|
||||||
if (FAILED(hr) ||
|
|
||||||
!(support.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Transport texture format is unsupported");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
DEBUG_TRACE("Creating transport texture for %p", base);
|
|
||||||
resName = L"Transport Texture";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DEBUG_TRACE("Creating transport buffer for %p", base);
|
|
||||||
resName = L"Transport Buffer";
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = dx12->GetDevice()->CreatePlacedResource(
|
hr = dx12->GetDevice()->CreatePlacedResource(
|
||||||
dx12->GetTransportHeap().Get(),
|
dx12->GetTransportHeap().Get(),
|
||||||
@@ -184,11 +138,8 @@ bool CFrameBufferResource::Init(CD3D12Device * dx12,
|
|||||||
m_res->SetName(resName);
|
m_res->SetName(resName);
|
||||||
|
|
||||||
m_base = base;
|
m_base = base;
|
||||||
m_size = type == RESOURCE_TEXTURE ?
|
m_size = size;
|
||||||
(size_t)allocationSize : size;
|
|
||||||
m_frameSize = size;
|
m_frameSize = size;
|
||||||
m_type = type;
|
|
||||||
m_desc = desc;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,8 +154,6 @@ void CFrameBufferResource::Reset()
|
|||||||
m_base = nullptr;
|
m_base = nullptr;
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
m_frameSize = 0;
|
m_frameSize = 0;
|
||||||
m_type = RESOURCE_NONE;
|
|
||||||
m_desc = {};
|
|
||||||
m_fullCopy = false;
|
m_fullCopy = false;
|
||||||
m_nbCopyDirtyRects = 0;
|
m_nbCopyDirtyRects = 0;
|
||||||
m_copyPitch = 0;
|
m_copyPitch = 0;
|
||||||
|
|||||||
@@ -37,13 +37,6 @@ using namespace Microsoft::WRL;
|
|||||||
class CFrameBufferResource
|
class CFrameBufferResource
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
enum ResourceType
|
|
||||||
{
|
|
||||||
RESOURCE_NONE,
|
|
||||||
RESOURCE_BUFFER,
|
|
||||||
RESOURCE_TEXTURE,
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned m_frameIndex = 0;
|
unsigned m_frameIndex = 0;
|
||||||
uint8_t * m_base = nullptr;
|
uint8_t * m_base = nullptr;
|
||||||
size_t m_size = 0;
|
size_t m_size = 0;
|
||||||
@@ -62,16 +55,13 @@ class CFrameBufferResource
|
|||||||
unsigned m_copyPitch = 0;
|
unsigned m_copyPitch = 0;
|
||||||
unsigned m_copyBytesPerPixel = 0;
|
unsigned m_copyBytesPerPixel = 0;
|
||||||
unsigned m_candidateIndex = 0;
|
unsigned m_candidateIndex = 0;
|
||||||
ResourceType m_type = RESOURCE_NONE;
|
|
||||||
D3D12_RESOURCE_DESC m_desc = {};
|
|
||||||
std::atomic<bool> m_completionHandled = false;
|
std::atomic<bool> m_completionHandled = false;
|
||||||
ComPtr<ID3D12Resource> m_res;
|
ComPtr<ID3D12Resource> m_res;
|
||||||
void * m_map = nullptr;
|
void * m_map = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Init(CD3D12Device * dx12, unsigned frameIndex, uint8_t * base,
|
bool Init(CD3D12Device * dx12, unsigned frameIndex, uint8_t * base,
|
||||||
uint64_t heapOffset, size_t size, size_t maxFrameSize,
|
uint64_t heapOffset, size_t size, size_t maxFrameSize);
|
||||||
const D3D12_RESOURCE_DESC * textureDesc = nullptr);
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
unsigned GetFrameIndex() { return m_frameIndex; }
|
unsigned GetFrameIndex() { return m_frameIndex; }
|
||||||
|
|||||||
@@ -32,9 +32,7 @@ CSoftwareFrameProcessor::CSoftwareFrameProcessor(
|
|||||||
CPostProcessor postProcessors[CAPTURE_PIPELINE_SLOTS],
|
CPostProcessor postProcessors[CAPTURE_PIPELINE_SLOTS],
|
||||||
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
|
SRWLOCK * pipelineLock, HANDLE terminateEvent) :
|
||||||
CFrameProcessor(transport, std::move(dx12), postProcessors,
|
CFrameProcessor(transport, std::move(dx12), postProcessors,
|
||||||
pipelineLock, terminateEvent),
|
pipelineLock, terminateEvent)
|
||||||
m_directTexture(
|
|
||||||
!m_dx12->IsIndirectCopy() && m_dx12->CanUseDirectTexture())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,48 +116,11 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
|
|||||||
CPostProcessor& postProcessor = m_postProcessors[0];
|
CPostProcessor& postProcessor = m_postProcessors[0];
|
||||||
const D12FrameFormat& dstFormat = postProcessor.GetOutputFormat();
|
const D12FrameFormat& dstFormat = postProcessor.GetOutputFormat();
|
||||||
|
|
||||||
D3D12_RESOURCE_DESC textureDesc = {};
|
// A copyable footprint describes a buffer layout, not the physical layout
|
||||||
const D3D12_RESOURCE_DESC * textureDescPtr = nullptr;
|
// of a row-major texture. Use that explicit buffer layout so the pitch sent
|
||||||
unsigned pitch = postProcessor.GetOutputPitch();
|
// through KVMFR always matches the bytes written into transport memory.
|
||||||
size_t frameSize = postProcessor.GetOutputSize();
|
const unsigned pitch = postProcessor.GetOutputPitch();
|
||||||
if (m_directTexture &&
|
const size_t frameSize = postProcessor.GetOutputSize();
|
||||||
dstFormat.desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D &&
|
|
||||||
dstFormat.desc.Width && dstFormat.desc.Height &&
|
|
||||||
dstFormat.desc.Format != DXGI_FORMAT_UNKNOWN)
|
|
||||||
{
|
|
||||||
textureDesc = dstFormat.desc;
|
|
||||||
textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
|
||||||
textureDesc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
|
|
||||||
textureDesc.DepthOrArraySize = 1;
|
|
||||||
textureDesc.MipLevels = 1;
|
|
||||||
textureDesc.SampleDesc.Count = 1;
|
|
||||||
textureDesc.SampleDesc.Quality = 0;
|
|
||||||
textureDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
|
||||||
textureDesc.Flags =
|
|
||||||
D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER;
|
|
||||||
|
|
||||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout = {};
|
|
||||||
m_dx12->GetDevice()->GetCopyableFootprints(
|
|
||||||
&textureDesc, 0, 1, 0, &layout, nullptr, nullptr, nullptr);
|
|
||||||
const unsigned texturePitch = layout.Footprint.RowPitch;
|
|
||||||
if (texturePitch && textureDesc.Height <=
|
|
||||||
m_transport->GetMaxFrameSize() / texturePitch)
|
|
||||||
{
|
|
||||||
pitch = texturePitch;
|
|
||||||
frameSize = (size_t)pitch * textureDesc.Height;
|
|
||||||
textureDescPtr = &textureDesc;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_directTexture = false;
|
|
||||||
DEBUG_WARN("Transport texture layout does not fit the framebuffer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (m_directTexture)
|
|
||||||
{
|
|
||||||
m_directTexture = false;
|
|
||||||
DEBUG_WARN("Post-processor output cannot use a transport texture");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pitch || !frameSize || frameSize > m_transport->GetMaxFrameSize())
|
if (!pitch || !frameSize || frameSize > m_transport->GetMaxFrameSize())
|
||||||
{
|
{
|
||||||
@@ -243,35 +204,8 @@ bool CSoftwareFrameProcessor::Submit(const FrameSubmission& submission)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFrameBufferResource * fbRes = nullptr;
|
CFrameBufferResource * fbRes =
|
||||||
if (textureDescPtr)
|
m_frameBuffers.Get(buffer, frameSize);
|
||||||
{
|
|
||||||
fbRes = m_frameBuffers.Get(buffer, frameSize, textureDescPtr);
|
|
||||||
if (!fbRes)
|
|
||||||
{
|
|
||||||
const HRESULT deviceStatus =
|
|
||||||
m_dx12->GetDevice()->GetDeviceRemovedReason();
|
|
||||||
if (FAILED(deviceStatus))
|
|
||||||
{
|
|
||||||
copySlot->Cancel();
|
|
||||||
m_transport->AbortFrameBuffer(buffer.frameIndex);
|
|
||||||
RestorePendingDamage(
|
|
||||||
currentDirtyRects, nbDirtyRects, hasDamage);
|
|
||||||
DEBUG_ERROR_HR(deviceStatus,
|
|
||||||
"D3D12 device removed while creating a transport texture");
|
|
||||||
SetFullDamage();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_directTexture = false;
|
|
||||||
textureDescPtr = nullptr;
|
|
||||||
DEBUG_WARN(
|
|
||||||
"Transport textures unavailable; using a direct buffer copy");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fbRes)
|
|
||||||
fbRes = m_frameBuffers.Get(buffer, frameSize);
|
|
||||||
if (!fbRes)
|
if (!fbRes)
|
||||||
{
|
{
|
||||||
copySlot->Cancel();
|
copySlot->Cancel();
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
class CSoftwareFrameProcessor final : public CFrameProcessor
|
class CSoftwareFrameProcessor final : public CFrameProcessor
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool m_directTexture;
|
|
||||||
|
|
||||||
static void CompletionFunction(
|
static void CompletionFunction(
|
||||||
CD3D12CommandSlot * slot, bool result, void * param1, void * param2);
|
CD3D12CommandSlot * slot, bool result, void * param1, void * param2);
|
||||||
|
|
||||||
|
|||||||
@@ -120,9 +120,6 @@ CD3D12Device::InitResult CD3D12Device::Init(
|
|||||||
|
|
||||||
D3D12_HEAP_DESC heapDesc = m_transportHeap->GetDesc();
|
D3D12_HEAP_DESC heapDesc = m_transportHeap->GetDesc();
|
||||||
alignSize = heapDesc.Alignment;
|
alignSize = heapDesc.Alignment;
|
||||||
m_directTextureSupported =
|
|
||||||
(heapDesc.Flags & D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER) &&
|
|
||||||
!(heapDesc.Flags & D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES);
|
|
||||||
|
|
||||||
// test that the heap is usable
|
// test that the heap is usable
|
||||||
if (!HeapTest())
|
if (!HeapTest())
|
||||||
@@ -136,8 +133,6 @@ CD3D12Device::InitResult CD3D12Device::Init(
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_INFO("Using transport memory as a D3D12 heap");
|
DEBUG_INFO("Using transport memory as a D3D12 heap");
|
||||||
if (!m_directTextureSupported)
|
|
||||||
DEBUG_WARN("Transport memory does not support placed textures");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_copyQueue.Init(m_device.Get(), D3D12_COMMAND_LIST_TYPE_COPY,
|
if (!m_copyQueue.Init(m_device.Get(), D3D12_COMMAND_LIST_TYPE_COPY,
|
||||||
|
|||||||
@@ -52,9 +52,8 @@ struct CD3D12Device
|
|||||||
|
|
||||||
CD3D12CommandQueue m_copyQueue;
|
CD3D12CommandQueue m_copyQueue;
|
||||||
CD3D12CommandQueue m_computeQueue;
|
CD3D12CommandQueue m_computeQueue;
|
||||||
bool m_computeEnabled = false;
|
bool m_computeEnabled = false;
|
||||||
bool m_indirectCopy = true;
|
bool m_indirectCopy = true;
|
||||||
bool m_directTextureSupported = false;
|
|
||||||
|
|
||||||
bool HeapTest();
|
bool HeapTest();
|
||||||
|
|
||||||
@@ -81,7 +80,6 @@ struct CD3D12Device
|
|||||||
ComPtr<ID3D12Device3> GetDevice() { return m_device; }
|
ComPtr<ID3D12Device3> GetDevice() { return m_device; }
|
||||||
ComPtr<ID3D12Heap > GetTransportHeap() { return m_transportHeap; }
|
ComPtr<ID3D12Heap > GetTransportHeap() { return m_transportHeap; }
|
||||||
bool IsIndirectCopy() const { return m_indirectCopy; }
|
bool IsIndirectCopy() const { return m_indirectCopy; }
|
||||||
bool CanUseDirectTexture() const { return m_directTextureSupported; }
|
|
||||||
|
|
||||||
CD3D12CommandSlot * GetCopySlot ();
|
CD3D12CommandSlot * GetCopySlot ();
|
||||||
CD3D12CommandSlot * GetCopySlot (unsigned frameIndex);
|
CD3D12CommandSlot * GetCopySlot (unsigned frameIndex);
|
||||||
|
|||||||
Reference in New Issue
Block a user