Привязка текстур DirectX 12 вызывает ошибку memcpyC++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Привязка текстур DirectX 12 вызывает ошибку memcpy

Сообщение Anonymous »

Я долго и упорно пытался решить эту проблему. Итак... Ребята, я обращаюсь ко всем вам! Проблема в том, что в каждом кадре я пытаюсь привязать свою текстуру:

Код: Выделить всё

Texture.hpp

Код: Выделить всё

class Texture : public Component
{
public:

void Bind()
{
auto commandList = Renderer::GetInstance()->GetCommandList();

UpdateSubresources(commandList.Get(), texture.Get(), textureUploadHeap.Get(), 0, 0, 1, &subresourceData);

CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
commandList->ResourceBarrier(1, &barrier);
}

void CleanUp() override
{
texture.Reset();
textureUploadHeap.Reset();
}

ComPtr GetRaw()
{
return texture;
}

String GetName()
{
return name;
}

static Shared Create(const String& name, const String& localPath, const String& domain = Settings::GetInstance()->Get("defaultDomain"))
{
Shared out = std::make_shared();

out->name = name;
out->localPath = localPath;
out->path = "Assets/" + domain + "/" + localPath;
out->Generate();

return out;
}

private:

void Generate()
{
ComPtr factory;
ComPtr decoder;
ComPtr frame;
ComPtr converter;

HRESULT result = CoInitializeEx(nullptr, COINITBASE_MULTITHREADED);

if (FAILED(result))
throw std::runtime_error("Failed to initialize COM library.");

result = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory));

if (FAILED(result))
throw std::runtime_error("Failed to create WIC Imaging Factory.");

result = factory->CreateDecoderFromFilename(WString(path.begin(), path.end()).c_str(), nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &decoder);

if (FAILED(result))
throw std::runtime_error("Failed to load image.");

result = decoder->GetFrame(0, &frame);

if (FAILED(result))
throw std::runtime_error("Failed to get image frame.");

result = factory->CreateFormatConverter(&converter);

if (FAILED(result))
throw std::runtime_error("Failed to create WIC format converter.");

result = converter->Initialize(frame.Get(), GUID_WICPixelFormat32bppRGBA, WICBitmapDitherTypeNone, nullptr, 0.0, WICBitmapPaletteTypeCustom);

if (FAILED(result))
throw std::runtime_error("Failed to initialize WIC format converter.");

UINT width, height;

result = converter->GetSize(&width, &height);

if (FAILED(result))
throw std::runtime_error("Failed to get image dimensions.");

Vector  imageData(width * height * 4);

result = converter->CopyPixels(nullptr, width * 4, static_cast(imageData.size()), imageData.data());

if (FAILED(result))
throw std::runtime_error("Failed to copy image pixels.");

auto device = Renderer::GetInstance()->GetDevice();

D3D12_RESOURCE_DESC textureDescription = {};

textureDescription.MipLevels = 1;
textureDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDescription.Width = width;
textureDescription.Height = height;
textureDescription.Flags = D3D12_RESOURCE_FLAG_NONE;
textureDescription.DepthOrArraySize = 1;
textureDescription.SampleDesc.Count = 1;
textureDescription.SampleDesc.Quality = 0;
textureDescription.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;

CD3DX12_HEAP_PROPERTIES heapProperties(D3D12_HEAP_TYPE_DEFAULT);

result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &textureDescription, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&texture));

if (FAILED(result))
throw std::runtime_error("Failed to create texture resource.");

const UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture.Get(), 0, 1);

CD3DX12_HEAP_PROPERTIES uploadHeapProperties(D3D12_HEAP_TYPE_UPLOAD);
CD3DX12_RESOURCE_DESC bufferDescription = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize);

result = device->CreateCommittedResource(&uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &bufferDescription, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&textureUploadHeap));

if (FAILED(result))
throw std::runtime_error("Failed to create texture upload heap.");

D3D12_SUBRESOURCE_DATA textureData = {};

textureData.pData = imageData.data();
textureData.RowPitch = static_cast(width) * 4;
textureData.SlicePitch = textureData.RowPitch * height;

subresourceData = textureData;
}

String name;
String localPath;
String path;

ComPtr texture;
ComPtr textureUploadHeap;

D3D12_SUBRESOURCE_DATA subresourceData = {};
};

Код: Выделить всё

Texture#Bind()
вызывается один раз для каждого кадра перед привязкой шейдера.

Код: Выделить всё

Texture#Create()
вызывается еще до создания сетки и вызывается один раз в начале программы. Он не вызывается для каждой созданной сетки (это было бы очень неэффективно!)
Чтобы помочь вам понять, вот мой класс шейдера:

Код: Выделить всё

Shader.hpp

Код: Выделить всё

class Shader : public Component
{
public:

void Bind()
{
auto commandList = Renderer::GetInstance()->GetCommandList();

if (rootSignature)
commandList->SetGraphicsRootSignature(rootSignature.Get());

if (pipelineState)
commandList->SetPipelineState(pipelineState.Get());

ID3D12DescriptorHeap* descriptorHeaps[] = { constantBufferViewShaderResourceViewUnorderedAccessViewHeap.Get(), samplerHeap.Get() };
commandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);

if (!constantBuffers.empty() && !constantBufferDatas.empty())
commandList->SetGraphicsRootDescriptorTable(0, constantBufferViewShaderResourceViewUnorderedAccessViewHeap->GetGPUDescriptorHandleForHeapStart());

if (!textures.empty())
commandList->SetGraphicsRootDescriptorTable(1, samplerHeap->GetGPUDescriptorHandleForHeapStart());
}

void CreateConstantBuffer(UINT bufferSize, UINT bufferIndex)
{
if (bufferIndex >= constantBuffers.size())
constantBuffers.resize(static_cast(bufferIndex) + 1);

CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_UPLOAD);
CD3DX12_RESOURCE_DESC bufferDescription = CD3DX12_RESOURCE_DESC::Buffer(bufferSize);

HRESULT result = Renderer::GetInstance()->GetDevice()->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &bufferDescription, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&constantBuffers[bufferIndex]));

if (FAILED(result))
Logger_ThrowError("D3D12", "Failed to create constant buffer", true);

constantBuffers[bufferIndex]->Map(0, nullptr, reinterpret_cast(&constantBufferDatas[bufferIndex]));

D3D12_CONSTANT_BUFFER_VIEW_DESC constantBufferViewDecription = {};

constantBufferViewDecription.BufferLocation = constantBuffers[bufferIndex]->GetGPUVirtualAddress();
constantBufferViewDecription.SizeInBytes = (bufferSize + 255) & ~255;

CD3DX12_CPU_DESCRIPTOR_HANDLE constantBufferViewHandle(constantBufferViewShaderResourceViewUnorderedAccessViewHeap->GetCPUDescriptorHandleForHeapStart(), bufferIndex, constantBufferViewShaderResourceViewUnorderedAccessViewDescriptorSize);
Renderer::GetInstance()->GetDevice()->CreateConstantBufferView(&constantBufferViewDecription, constantBufferViewHandle);
}

void UpdateConstantBuffer(const void* data, Size dataSize, UINT bufferIndex)
{
memcpy(constantBufferDatas[bufferIndex], data, dataSize);
}

void CreateTexture(ComPtr  resource, UINT textureIndex)
{
if (textureIndex >= textures.size())
textures.resize(static_cast(textureIndex) + 1);

textures[textureIndex] = resource;

D3D12_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDescription = {};

shaderResourceViewDescription.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
shaderResourceViewDescription.Format = resource->GetDesc().Format;
shaderResourceViewDescription.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDescription.Texture2D.MipLevels = resource->GetDesc().MipLevels;

CD3DX12_CPU_DESCRIPTOR_HANDLE shaderResourceViewHandle(constantBufferViewShaderResourceViewUnorderedAccessViewHeap->GetCPUDescriptorHandleForHeapStart(), textureIndex + maxConstantBuffers, constantBufferViewShaderResourceViewUnorderedAccessViewDescriptorSize);
Renderer::GetInstance()->GetDevice()->CreateShaderResourceView(resource.Get(), &shaderResourceViewDescription, shaderResourceViewHandle);
}

void CreateSampler(UINT samplerIndex)
{
if (samplerIndex >= samplers.size())
samplers.resize(static_cast(samplerIndex) + 1);

D3D12_SAMPLER_DESC samplerDescription = {};

samplerDescription.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
samplerDescription.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
samplerDescription.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
samplerDescription.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
samplerDescription.MinLOD = 0;
samplerDescription.MaxLOD = D3D12_FLOAT32_MAX;
samplerDescription.MipLODBias = 0.0f;
samplerDescription.MaxAnisotropy = 1;
samplerDescription.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;

CD3DX12_CPU_DESCRIPTOR_HANDLE samplerHandle(samplerHeap->GetCPUDescriptorHandleForHeapStart(), samplerIndex, samplerDescriptorSize);
Renderer::GetInstance()->GetDevice()->CreateSampler(&samplerDescription, samplerHandle);
}

String GetName() const
{
return name;
}

String GetLocalPath() const
{
return localPath;
}

String GetDomain() const
{
return domain;
}

UnorderedMap GetPaths() const
{
return
{
{ "vertex", vertexPath },
{ "pixel", pixelPath },
{ "compute", computePath },
{ "geometry", geometryPath },
{ "hull", hullPath },
{ "domain", domainPath }
};
}

ComPtr GetRootSignature() const
{
return rootSignature;
}

ComPtr GetPipelineState() const
{
return pipelineState;
}

void CleanUp()
{
for (auto& buffer : constantBuffers)
{
if (buffer)
buffer->Unmap(0, nullptr);
}
}

static Shared Create(const String& name, const String& localPath, Shared rootSignature, const String& domain = Settings::GetInstance()->Get("defaultDomain"))
{
Shared out = std::make_shared();

out->name = name;
out->localPath = localPath;
out->domain = domain;
out->vertexPath = "Assets/" + domain + "/" + localPath + "Vertex.hlsl";
out->pixelPath = "Assets/" + domain + "/" + localPath + "Pixel.hlsl";
out->computePath = "Assets/" + domain + "/" + localPath + "Compute.hlsl";
out->geometryPath = "Assets/" + domain + "/" + localPath + "Geometry.hlsl";
out->hullPath = "Assets/" + domain + "/" + localPath + "Hull.hlsl";
out->domainPath = "Assets/" + domain + "/"  + localPath + "Domain.hlsl";
out->rootSignature = rootSignature->Generate();

out->Generate();

return std::move(out);
}

private:

void Generate()
{
//Just compiles shaders and creates the pso
}

void CreateDescriptorHeaps()
{
D3D12_DESCRIPTOR_HEAP_DESC constantBufferViewShaderResourceViewUnorderedAccessViewHeapDescription = {};

constantBufferViewShaderResourceViewUnorderedAccessViewHeapDescription.NumDescriptors = maxConstantBuffers + maxTextures;
constantBufferViewShaderResourceViewUnorderedAccessViewHeapDescription.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
constantBufferViewShaderResourceViewUnorderedAccessViewHeapDescription.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;

HRESULT result = Renderer::GetInstance()->GetDevice()->CreateDescriptorHeap(&constantBufferViewShaderResourceViewUnorderedAccessViewHeapDescription, IID_PPV_ARGS(&constantBufferViewShaderResourceViewUnorderedAccessViewHeap));

if (FAILED(result))
Logger_ThrowError("D3D12", "Failed to create CBV/SRV/UAV descriptor heap", true);

constantBufferViewShaderResourceViewUnorderedAccessViewDescriptorSize = Renderer::GetInstance()->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);

D3D12_DESCRIPTOR_HEAP_DESC samplerHeapDescription = {};

samplerHeapDescription.NumDescriptors = maxTextures;
samplerHeapDescription.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
samplerHeapDescription.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;

result = Renderer::GetInstance()->GetDevice()->CreateDescriptorHeap(&samplerHeapDescription, IID_PPV_ARGS(&samplerHeap));

if (FAILED(result))
Logger_ThrowError("D3D12", "Failed to create sampler descriptor heap", true);

samplerDescriptorSize = Renderer::GetInstance()->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
}

ComPtr CompileShader(ComPtr& utils, ComPtr& compiler, ComPtr& includeHandler, const String& path, const wchar_t* target)
{
//Long and compilicated function...
}

void CreateGraphicsPipelineState(ComPtr& vertexShaderBlob, ComPtr& pixelShaderBlob, ComPtr& geometryShaderBlob, ComPtr& hullShaderBlob, ComPtr&  domainShaderBlob)
{
D3D12_GRAPHICS_PIPELINE_STATE_DESC pipelineStateDescription = {};

pipelineStateDescription.VS = vertexShaderBlob ? D3D12_SHADER_BYTECODE{ vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize() } : D3D12_SHADER_BYTECODE{};
pipelineStateDescription.PS = pixelShaderBlob ? D3D12_SHADER_BYTECODE{ pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize() } : D3D12_SHADER_BYTECODE{};
pipelineStateDescription.GS = geometryShaderBlob ? D3D12_SHADER_BYTECODE{ geometryShaderBlob->GetBufferPointer(), geometryShaderBlob->GetBufferSize() } : D3D12_SHADER_BYTECODE{};
pipelineStateDescription.HS = hullShaderBlob ? D3D12_SHADER_BYTECODE{ hullShaderBlob->GetBufferPointer(), hullShaderBlob->GetBufferSize() } : D3D12_SHADER_BYTECODE{};
pipelineStateDescription.DS = domainShaderBlob ? D3D12_SHADER_BYTECODE{ domainShaderBlob->GetBufferPointer(), domainShaderBlob->GetBufferSize() } : D3D12_SHADER_BYTECODE{};

pipelineStateDescription.pRootSignature = rootSignature.Get();
pipelineStateDescription.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
pipelineStateDescription.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
pipelineStateDescription.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
pipelineStateDescription.InputLayout = { Vertex::GetInputLayout().data(), (uint)Vertex::GetInputLayout().size() };
pipelineStateDescription.SampleMask = UINT_MAX;
pipelineStateDescription.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
pipelineStateDescription.NumRenderTargets = 1;
pipelineStateDescription.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
pipelineStateDescription.DSVFormat = DXGI_FORMAT_D32_FLOAT;
pipelineStateDescription.SampleDesc.Count = 1;

HRESULT result = Renderer::GetInstance()->GetDevice()->CreateGraphicsPipelineState(&pipelineStateDescription, IID_PPV_ARGS(&pipelineState));

if (FAILED(result))
Logger_ThrowError("FAILED", "Failed to create graphics pipeline state", true);
}

//Member variables
};
И, наконец, порядок вызова операций:

Код: Выделить всё

void Render()
{
if (!shader) //'shader' and 'texture' are both std::shared_ptr
return;

texture->Bind();
shader->Bind();

UINT stride = sizeof(Vertex);
UINT offset = 0;

ComPtr commandList = Renderer::GetInstance()->GetCommandList();

commandList->IASetVertexBuffers(0, 1, &vertexBufferView);
commandList->IASetIndexBuffer(&indexBufferView);
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

commandList->DrawIndexedInstanced(static_cast(indices.size()), 1, 0, 0, 0);
}
Я пробовал использовать ChatGPT, смотрел Microsoft Learn и создавал минимальный воспроизводимый пример, но ничего не помогло. Я просто не могу найти правильный способ установки текстуры!

Подробнее здесь: https://stackoverflow.com/questions/785 ... mcpy-error
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»