Anonymous
Привязка текстур DirectX 12 вызывает ошибку memcpy
Сообщение
Anonymous » 29 май 2024, 08:56
Я долго и упорно пытался решить эту проблему. Итак... Ребята, я обращаюсь ко всем вам! Проблема в том, что в каждом кадре я пытаюсь привязать свою текстуру:
Код: Выделить всё
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 = {};
};
вызывается один раз для каждого кадра перед привязкой шейдера.
вызывается еще до создания сетки и вызывается один раз в начале программы. Он не вызывается для каждой созданной сетки (это было бы очень неэффективно!)
Чтобы помочь вам понять, вот мой класс шейдера:
Код: Выделить всё
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
1716962174
Anonymous
Я долго и упорно пытался решить эту проблему. Итак... Ребята, я обращаюсь ко всем вам! Проблема в том, что в каждом кадре я пытаюсь привязать свою текстуру: [code]Texture.hpp[/code] [code]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 = {}; }; [/code] [code]Texture#Bind()[/code] вызывается один раз для каждого кадра перед привязкой шейдера. [code]Texture#Create()[/code] вызывается еще до создания сетки и вызывается один раз в начале программы. Он не вызывается для каждой созданной сетки (это было бы очень неэффективно!) Чтобы помочь вам понять, вот мой класс шейдера: [code]Shader.hpp[/code] [code]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 }; [/code] И, наконец, порядок вызова операций: [code]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); } [/code] Я пробовал использовать ChatGPT, смотрел Microsoft Learn и создавал минимальный воспроизводимый пример, но ничего не помогло. Я просто не могу найти правильный способ установки текстуры! Подробнее здесь: [url]https://stackoverflow.com/questions/78547559/directx-12-texture-binding-causes-memcpy-error[/url]