Fix RHI texture binding and add pure quad test

This commit is contained in:
2026-03-26 00:47:12 +08:00
parent 76c4c2ace2
commit 9adac63b4c
20 changed files with 711 additions and 53 deletions

View File

@@ -142,6 +142,7 @@ inline DXGI_FORMAT ToD3D12(Format format) {
case Format::R32G32B32A32_Float: return DXGI_FORMAT_R32G32B32A32_FLOAT;
case Format::R16_Float: return DXGI_FORMAT_R16_FLOAT;
case Format::R32_Float: return DXGI_FORMAT_R32_FLOAT;
case Format::R32G32_Float: return DXGI_FORMAT_R32G32_FLOAT;
case Format::D16_UNorm: return DXGI_FORMAT_D16_UNORM;
case Format::D24_UNorm_S8_UInt: return DXGI_FORMAT_D24_UNORM_S8_UINT;
case Format::D32_Float: return DXGI_FORMAT_D32_FLOAT;
@@ -168,6 +169,7 @@ inline Format FromD3D12(DXGI_FORMAT format) {
case DXGI_FORMAT_R32G32B32A32_FLOAT: return Format::R32G32B32A32_Float;
case DXGI_FORMAT_R16_FLOAT: return Format::R16_Float;
case DXGI_FORMAT_R32_FLOAT: return Format::R32_Float;
case DXGI_FORMAT_R32G32_FLOAT: return Format::R32G32_Float;
case DXGI_FORMAT_D16_UNORM: return Format::D16_UNorm;
case DXGI_FORMAT_D24_UNORM_S8_UINT: return Format::D24_UNorm_S8_UInt;
case DXGI_FORMAT_D32_FLOAT: return Format::D32_Float;
@@ -319,4 +321,4 @@ inline D3D12_COMMAND_LIST_TYPE ToD3D12(CommandQueueType type) {
}
} // namespace RHI
} // namespace XCEngine
} // namespace XCEngine

View File

@@ -3,6 +3,7 @@
#include <d3d12.h>
#include <wrl/client.h>
#include <unordered_map>
#include <vector>
#include "../RHIPipelineLayout.h"
#include "D3D12RootSignature.h"
@@ -36,7 +37,8 @@ private:
D3D12Device* m_device;
std::unordered_map<uint32_t, uint32_t> m_registerToRootIndex;
std::vector<D3D12_ROOT_PARAMETER> m_rootParameters;
std::vector<D3D12_DESCRIPTOR_RANGE> m_descriptorRanges;
};
} // namespace RHI
} // namespace XCEngine
} // namespace XCEngine

View File

@@ -19,7 +19,7 @@ public:
bool Initialize(ID3D12Device* device, const D3D12_SAMPLER_DESC& desc);
void Shutdown() override;
D3D12_SAMPLER_DESC GetDesc() const { return m_desc; }
const D3D12_SAMPLER_DESC& GetDesc() const { return m_desc; }
void* GetNativeHandle() override { return &m_desc; }
unsigned int GetID() override { return m_id; }

View File

@@ -20,7 +20,8 @@ public:
bool Initialize(ID3D12Device* device, const D3D12_RESOURCE_DESC& desc, D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON);
bool InitializeFromExisting(ID3D12Resource* resource, bool ownsResource = false);
bool InitializeFromData(ID3D12Device* device, ID3D12GraphicsCommandList* commandList,
const void* pixelData, uint32_t width, uint32_t height, DXGI_FORMAT format, uint32_t rowPitch = 0);
const void* pixelData, uint32_t width, uint32_t height, DXGI_FORMAT format, uint32_t rowPitch = 0,
ComPtr<ID3D12Resource>* uploadBuffer = nullptr);
bool InitializeDepthStencil(ID3D12Device* device, uint32_t width, uint32_t height, DXGI_FORMAT format = DXGI_FORMAT_D24_UNORM_S8_UINT);
void Shutdown() override;

View File

@@ -126,6 +126,9 @@ inline void ToOpenGLFormat(OpenGLFormat fmt, GLint& internalFormat, GLenum& glFo
case OpenGLFormat::RG8:
internalFormat = GL_RG8; glFormat = GL_RG; glType = GL_UNSIGNED_BYTE;
break;
case OpenGLFormat::RG32F:
internalFormat = GL_RG32F; glFormat = GL_RG; glType = GL_FLOAT;
break;
case OpenGLFormat::RGBA8:
internalFormat = GL_RGBA8; glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE;
break;

View File

@@ -20,6 +20,7 @@ enum class OpenGLTextureType {
enum class OpenGLFormat {
R8,
RG8,
RG32F,
RGBA8,
RGBA16F,
RGBA32F,
@@ -32,6 +33,7 @@ enum class OpenGLFormat {
enum class OpenGLInternalFormat {
R8 = 1,
RG8 = 2,
RG32F = 13,
RGBA8 = 4,
RGBA16F = 11,
RGBA32F = 16,

View File

@@ -314,7 +314,8 @@ enum class Format : uint32_t {
BC6H_UF16,
BC7_UNorm,
R32G32B32A32_UInt,
R32_UInt
R32_UInt,
R32G32_Float
};
enum class ResourceStates : uint32_t {

View File

@@ -37,6 +37,7 @@ bool D3D12DescriptorHeap::Initialize(ID3D12Device* device, DescriptorHeapType ty
return false;
}
m_device = device;
m_type = type;
m_numDescriptors = numDescriptors;
m_shaderVisible = shaderVisible;
@@ -47,6 +48,7 @@ bool D3D12DescriptorHeap::Initialize(ID3D12Device* device, DescriptorHeapType ty
}
void D3D12DescriptorHeap::Shutdown() {
m_device.Reset();
m_descriptorHeap.Reset();
m_allocatedSets.clear();
m_numDescriptors = 0;

View File

@@ -74,6 +74,8 @@ uint32_t GetFormatBytesPerPixel(Format format) {
return 8;
case Format::R32_Float:
return 4;
case Format::R32G32_Float:
return 8;
case Format::R32G32B32A32_Float:
return 16;
default:
@@ -390,6 +392,7 @@ RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc, const void* init
uploadCommandList.Reset();
auto* texture = new D3D12Texture();
ComPtr<ID3D12Resource> uploadBuffer;
if (!texture->InitializeFromData(
m_device.Get(),
uploadCommandList.GetCommandList(),
@@ -397,7 +400,8 @@ RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc, const void* init
desc.width,
desc.height,
ToD3D12(format),
resolvedRowPitch)) {
resolvedRowPitch,
&uploadBuffer)) {
delete texture;
uploadCommandList.Shutdown();
uploadAllocator.Shutdown();
@@ -411,6 +415,7 @@ RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc, const void* init
ID3D12CommandList* commandLists[] = { uploadCommandList.GetCommandList() };
uploadQueue.ExecuteCommandListsInternal(1, commandLists);
uploadQueue.WaitForIdle();
uploadBuffer.Reset();
uploadCommandList.Shutdown();
uploadAllocator.Shutdown();
@@ -442,13 +447,13 @@ RHIShader* D3D12Device::CreateShader(const ShaderCompileDesc& desc) {
RHISampler* D3D12Device::CreateSampler(const SamplerDesc& desc) {
auto* sampler = new D3D12Sampler();
D3D12_SAMPLER_DESC d3d12Desc = {};
d3d12Desc.Filter = static_cast<D3D12_FILTER>(desc.filter);
d3d12Desc.AddressU = static_cast<D3D12_TEXTURE_ADDRESS_MODE>(desc.addressU);
d3d12Desc.AddressV = static_cast<D3D12_TEXTURE_ADDRESS_MODE>(desc.addressV);
d3d12Desc.AddressW = static_cast<D3D12_TEXTURE_ADDRESS_MODE>(desc.addressW);
d3d12Desc.Filter = ToD3D12(static_cast<FilterMode>(desc.filter));
d3d12Desc.AddressU = ToD3D12(static_cast<TextureAddressMode>(desc.addressU));
d3d12Desc.AddressV = ToD3D12(static_cast<TextureAddressMode>(desc.addressV));
d3d12Desc.AddressW = ToD3D12(static_cast<TextureAddressMode>(desc.addressW));
d3d12Desc.MipLODBias = desc.mipLodBias;
d3d12Desc.MaxAnisotropy = desc.maxAnisotropy;
d3d12Desc.ComparisonFunc = static_cast<D3D12_COMPARISON_FUNC>(desc.comparisonFunc);
d3d12Desc.ComparisonFunc = ToD3D12(static_cast<ComparisonFunc>(desc.comparisonFunc));
d3d12Desc.BorderColor[0] = desc.borderColorR;
d3d12Desc.BorderColor[1] = desc.borderColorG;
d3d12Desc.BorderColor[2] = desc.borderColorB;
@@ -735,7 +740,7 @@ RHIResourceView* D3D12Device::CreateShaderResourceView(RHITexture* texture, cons
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
auto heap = std::make_unique<D3D12DescriptorHeap>();
if (!heap->Initialize(m_device.Get(), DescriptorHeapType::CBV_SRV_UAV, 1, true)) {
if (!heap->Initialize(m_device.Get(), DescriptorHeapType::CBV_SRV_UAV, 1, false)) {
delete view;
return nullptr;
}
@@ -756,7 +761,7 @@ RHIResourceView* D3D12Device::CreateUnorderedAccessView(RHITexture* texture, con
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
auto heap = std::make_unique<D3D12DescriptorHeap>();
if (!heap->Initialize(m_device.Get(), DescriptorHeapType::CBV_SRV_UAV, 1, true)) {
if (!heap->Initialize(m_device.Get(), DescriptorHeapType::CBV_SRV_UAV, 1, false)) {
delete view;
return nullptr;
}

View File

@@ -24,8 +24,20 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
m_device = device;
m_rootParameters.clear();
m_descriptorRanges.clear();
m_registerToRootIndex.clear();
const uint32_t rootParameterCount =
(desc.constantBufferCount > 0 ? 1u : 0u) +
(desc.textureCount > 0 ? 1u : 0u) +
(desc.samplerCount > 0 ? 1u : 0u);
const uint32_t descriptorRangeCount =
(desc.textureCount > 0 ? 1u : 0u) +
(desc.samplerCount > 0 ? 1u : 0u);
m_rootParameters.reserve(rootParameterCount);
m_descriptorRanges.reserve(descriptorRangeCount);
uint32_t rootIndex = 0;
if (desc.constantBufferCount > 0) {
@@ -39,9 +51,10 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
}
if (desc.textureCount > 0) {
D3D12_DESCRIPTOR_RANGE range = D3D12RootSignature::CreateDescriptorRange(
D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, desc.textureCount, 0);
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(1, &range, ShaderVisibility::All);
m_descriptorRanges.push_back(D3D12RootSignature::CreateDescriptorRange(
D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, desc.textureCount, 0));
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(
1, &m_descriptorRanges.back(), ShaderVisibility::All);
m_rootParameters.push_back(param);
for (uint32_t i = 0; i < desc.textureCount; ++i) {
m_registerToRootIndex[100 + i] = rootIndex;
@@ -50,9 +63,10 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
}
if (desc.samplerCount > 0) {
D3D12_DESCRIPTOR_RANGE range = D3D12RootSignature::CreateDescriptorRange(
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 0, desc.samplerCount, 0);
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(1, &range, ShaderVisibility::All);
m_descriptorRanges.push_back(D3D12RootSignature::CreateDescriptorRange(
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 0, desc.samplerCount, 0));
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(
1, &m_descriptorRanges.back(), ShaderVisibility::All);
m_rootParameters.push_back(param);
for (uint32_t i = 0; i < desc.samplerCount; ++i) {
m_registerToRootIndex[200 + i] = rootIndex;
@@ -99,6 +113,7 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
void D3D12PipelineLayout::Shutdown() {
m_rootSignature.Reset();
m_rootParameters.clear();
m_descriptorRanges.clear();
m_registerToRootIndex.clear();
m_device = nullptr;
}
@@ -116,4 +131,4 @@ bool D3D12PipelineLayout::HasRootParameter(uint32_t shaderRegister) const {
}
} // namespace RHI
} // namespace XCEngine
} // namespace XCEngine

View File

@@ -44,7 +44,8 @@ bool D3D12Texture::InitializeFromExisting(ID3D12Resource* resource, bool ownsRes
}
bool D3D12Texture::InitializeFromData(ID3D12Device* device, ID3D12GraphicsCommandList* commandList,
const void* pixelData, uint32_t width, uint32_t height, DXGI_FORMAT format, uint32_t rowPitch) {
const void* pixelData, uint32_t width, uint32_t height, DXGI_FORMAT format, uint32_t rowPitch,
ComPtr<ID3D12Resource>* uploadBuffer) {
D3D12_RESOURCE_DESC textureDesc = {};
textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
@@ -84,7 +85,7 @@ bool D3D12Texture::InitializeFromData(ID3D12Device* device, ID3D12GraphicsComman
device->GetCopyableFootprints(&textureDesc, 0, 1, 0,
&subresourceFootprint, &rowUsed, &rowSizeInBytes, &memorySizeUsed);
ID3D12Resource* tempBufferObject = nullptr;
ComPtr<ID3D12Resource> tempBufferObject;
D3D12_HEAP_PROPERTIES d3dTempHeapProperties = {};
d3dTempHeapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
@@ -107,7 +108,7 @@ bool D3D12Texture::InitializeFromData(ID3D12Device* device, ID3D12GraphicsComman
&d3d12TempResourceDesc,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&tempBufferObject)
IID_PPV_ARGS(tempBufferObject.GetAddressOf())
);
if (FAILED(hResult)) {
@@ -130,7 +131,7 @@ bool D3D12Texture::InitializeFromData(ID3D12Device* device, ID3D12GraphicsComman
dst.SubresourceIndex = 0;
D3D12_TEXTURE_COPY_LOCATION src = {};
src.pResource = tempBufferObject;
src.pResource = tempBufferObject.Get();
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
src.PlacedFootprint = subresourceFootprint;
commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
@@ -145,7 +146,9 @@ bool D3D12Texture::InitializeFromData(ID3D12Device* device, ID3D12GraphicsComman
commandList->ResourceBarrier(1, &barrier);
m_state = ResourceStates::PixelShaderResource;
tempBufferObject->Release();
if (uploadBuffer != nullptr) {
*uploadBuffer = tempBufferObject;
}
return true;
}

View File

@@ -40,6 +40,9 @@ bool GetOpenGLVertexAttribFormat(Format format, OpenGLVertexAttribFormat& attrib
case Format::R32_Float:
attributeFormat = { 1, GL_FLOAT, GL_FALSE, false };
return true;
case Format::R32G32_Float:
attributeFormat = { 2, GL_FLOAT, GL_FALSE, false };
return true;
case Format::R32G32B32A32_Float:
attributeFormat = { 4, GL_FLOAT, GL_FALSE, false };
return true;

View File

@@ -61,6 +61,29 @@ std::string SourceToString(const ShaderCompileDesc& desc) {
return std::string(reinterpret_cast<const char*>(desc.source.data()), desc.source.size());
}
OpenGLFormat ToOpenGLTextureFormat(Format format) {
switch (format) {
case Format::R8_UNorm:
return OpenGLFormat::R8;
case Format::R8G8_UNorm:
return OpenGLFormat::RG8;
case Format::R32G32_Float:
return OpenGLFormat::RG32F;
case Format::R8G8B8A8_UNorm:
return OpenGLFormat::RGBA8;
case Format::R16G16B16A16_Float:
return OpenGLFormat::RGBA16F;
case Format::R32G32B32A32_Float:
return OpenGLFormat::RGBA32F;
case Format::D24_UNorm_S8_UInt:
return OpenGLFormat::Depth24Stencil8;
case Format::D32_Float:
return OpenGLFormat::Depth32F;
default:
return OpenGLFormat::RGBA8;
}
}
} // namespace
OpenGLDevice::OpenGLDevice()
@@ -338,19 +361,7 @@ RHITexture* OpenGLDevice::CreateTexture(const TextureDesc& desc) {
break;
}
OpenGLFormat format = OpenGLFormat::RGBA8;
switch (desc.format) {
case 1: format = OpenGLFormat::R8; break;
case 2: format = OpenGLFormat::RG8; break;
case 3: format = OpenGLFormat::RGBA8; break;
case 4: format = OpenGLFormat::RGBA16F; break;
case 5: format = OpenGLFormat::RGBA32F; break;
case 6: format = OpenGLFormat::RGBA16F; break;
case 7: format = OpenGLFormat::RGBA32F; break;
case 8: format = OpenGLFormat::Depth24Stencil8; break;
case 9: format = OpenGLFormat::Depth32F; break;
default: format = OpenGLFormat::RGBA8; break;
}
OpenGLFormat format = ToOpenGLTextureFormat(static_cast<Format>(desc.format));
texture->Initialize(type, desc.width, desc.height, desc.depth, desc.mipLevels, format, nullptr);
texture->SetFormat(static_cast<Format>(desc.format));
return texture;
@@ -385,19 +396,7 @@ RHITexture* OpenGLDevice::CreateTexture(const TextureDesc& desc, const void* ini
break;
}
OpenGLFormat format = OpenGLFormat::RGBA8;
switch (desc.format) {
case 1: format = OpenGLFormat::R8; break;
case 2: format = OpenGLFormat::RG8; break;
case 3: format = OpenGLFormat::RGBA8; break;
case 4: format = OpenGLFormat::RGBA16F; break;
case 5: format = OpenGLFormat::RGBA32F; break;
case 6: format = OpenGLFormat::RGBA16F; break;
case 7: format = OpenGLFormat::RGBA32F; break;
case 8: format = OpenGLFormat::Depth24Stencil8; break;
case 9: format = OpenGLFormat::Depth32F; break;
default: format = OpenGLFormat::RGBA8; break;
}
OpenGLFormat format = ToOpenGLTextureFormat(static_cast<Format>(desc.format));
if (!texture->Initialize(type, desc.width, desc.height, desc.depth, desc.mipLevels, format, initialData)) {
delete texture;