Add depth-stencil textures and attachments (#77)

Related: #29
This commit is contained in:
Kai Ninomiya 2017-07-17 12:03:16 -04:00 committed by GitHub
parent 28684d93ed
commit fec8c58a97
24 changed files with 227 additions and 194 deletions

View File

@ -81,8 +81,10 @@ void frame() {
{
nxtCommandBufferBuilder builder = nxtDeviceCreateCommandBufferBuilder(device);
nxtCommandBufferBuilderBeginRenderPass(builder, renderpass, framebuffer);
nxtCommandBufferBuilderBeginRenderSubpass(builder);
nxtCommandBufferBuilderSetPipeline(builder, pipeline);
nxtCommandBufferBuilderDrawArrays(builder, 3, 1, 0, 0);
nxtCommandBufferBuilderEndRenderSubpass(builder);
nxtCommandBufferBuilderEndRenderPass(builder);
commands = nxtCommandBufferBuilderGetResult(builder);
nxtCommandBufferBuilderRelease(builder);

View File

@ -445,18 +445,7 @@ namespace {
device = CreateCppNXTDevice();
queue = device.CreateQueueBuilder().GetResult();
renderpass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.GetResult();
framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(renderpass)
// attachment 0 -> back buffer
// (implicit) // TODO(kainino@chromium.org): use the texture provided by WSI
.SetDimensions(640, 480)
.GetResult();
utils::CreateDefaultRenderPass(device, &renderpass, &framebuffer);
initBuffers();
initSamplers();

View File

@ -591,7 +591,7 @@
"name": "set attachment",
"args": [
{"name": "attachment slot", "type": "uint32_t"},
{"name": "texture views", "type": "texture view"}
{"name": "texture view", "type": "texture view"}
]
}
]
@ -762,6 +762,13 @@
{"name": "output attachment location", "type": "uint32_t"},
{"name": "attachment slot", "type": "uint32_t"}
]
},
{
"name": "subpass set depth stencil attachment",
"args": [
{"name": "subpass index", "type": "uint32_t"},
{"name": "attachment slot", "type": "uint32_t"}
]
}
]
},
@ -936,7 +943,8 @@
"texture format": {
"category": "enum",
"values": [
{"value": 0, "name": "r8 g8 b8 a8 unorm"}
{"value": 0, "name": "r8 g8 b8 a8 unorm"},
{"value": 1, "name": "d32 float s8 uint"}
]
},
"vertex format": {

View File

@ -126,6 +126,10 @@ namespace backend {
HandleError("Render pass subpass count not set yet");
return;
}
if ((propertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
HandleError("Render pass attachment count not set yet");
return;
}
if (subpass >= subpasses.size()) {
HandleError("Subpass index out of bounds");
return;
@ -147,4 +151,30 @@ namespace backend {
subpasses[subpass].colorAttachments[outputAttachmentLocation] = attachmentSlot;
}
void RenderPassBuilder::SubpassSetDepthStencilAttachment(uint32_t subpass, uint32_t attachmentSlot) {
if ((propertiesSet & RENDERPASS_PROPERTY_SUBPASS_COUNT) == 0) {
HandleError("Render pass subpass count not set yet");
return;
}
if ((propertiesSet & RENDERPASS_PROPERTY_ATTACHMENT_COUNT) == 0) {
HandleError("Render pass attachment count not set yet");
return;
}
if (subpass >= subpasses.size()) {
HandleError("Subpass index out of bounds");
return;
}
if (attachmentSlot >= attachments.size()) {
HandleError("Subpass attachment slot out of bounds");
return;
}
if (subpasses[subpass].depthStencilAttachmentSet) {
HandleError("Subpass depth-stencil attachment already set");
return;
}
subpasses[subpass].depthStencilAttachmentSet = true;
subpasses[subpass].depthStencilAttachment = attachmentSlot;
}
}

View File

@ -39,6 +39,8 @@ namespace backend {
struct SubpassInfo {
std::bitset<kMaxColorAttachments> colorAttachmentsSet;
std::array<uint32_t, kMaxColorAttachments> colorAttachments;
bool depthStencilAttachmentSet = false;
uint32_t depthStencilAttachment = 0;
};
uint32_t GetAttachmentCount() const;
@ -64,6 +66,7 @@ namespace backend {
void AttachmentSetFormat(uint32_t attachmentSlot, nxt::TextureFormat format);
void SetSubpassCount(uint32_t subpassCount);
void SubpassSetColorAttachment(uint32_t subpass, uint32_t outputAttachmentLocation, uint32_t attachmentSlot);
void SubpassSetDepthStencilAttachment(uint32_t subpass, uint32_t attachmentSlot);
private:
friend class RenderPassBase;

View File

@ -23,11 +23,36 @@ namespace backend {
switch (format) {
case nxt::TextureFormat::R8G8B8A8Unorm:
return 4;
case nxt::TextureFormat::D32FloatS8Uint:
return 8;
default:
UNREACHABLE();
}
}
bool TextureFormatHasDepth(nxt::TextureFormat format) {
switch (format) {
case nxt::TextureFormat::R8G8B8A8Unorm:
return false;
case nxt::TextureFormat::D32FloatS8Uint:
return true;
default:
UNREACHABLE();
}
}
bool TextureFormatHasStencil(nxt::TextureFormat format) {
switch (format) {
case nxt::TextureFormat::R8G8B8A8Unorm:
return false;
case nxt::TextureFormat::D32FloatS8Uint:
return true;
default:
UNREACHABLE();
}
}
// TextureBase
TextureBase::TextureBase(TextureBuilder* builder)
@ -95,15 +120,6 @@ namespace backend {
currentUsage = usage;
}
bool TextureBase::IsDepthFormat(nxt::TextureFormat format) {
switch (format) {
case nxt::TextureFormat::R8G8B8A8Unorm:
return false;
default:
UNREACHABLE();
}
}
void TextureBase::TransitionUsage(nxt::TextureUsageBit usage) {
if (!IsTransitionPossible(usage)) {
device->HandleError("Texture frozen or usage not allowed");

View File

@ -24,6 +24,8 @@
namespace backend {
size_t TextureFormatPixelSize(nxt::TextureFormat format);
bool TextureFormatHasDepth(nxt::TextureFormat format);
bool TextureFormatHasStencil(nxt::TextureFormat format);
class TextureBase : public RefCounted {
public:
@ -43,8 +45,6 @@ namespace backend {
bool IsTransitionPossible(nxt::TextureUsageBit usage) const;
void UpdateUsageInternal(nxt::TextureUsageBit usage);
static bool IsDepthFormat(nxt::TextureFormat format);
DeviceBase* GetDevice();
// NXT API

View File

@ -204,12 +204,7 @@ namespace d3d12 {
d3d12Location.PlacedFootprint.Footprint.Height = textureLocation.height;
d3d12Location.PlacedFootprint.Footprint.Depth = textureLocation.depth;
uint32_t texelSize = 0;
switch (texture->GetFormat()) {
case nxt::TextureFormat::R8G8B8A8Unorm:
texelSize = 4;
break;
}
size_t texelSize = TextureFormatPixelSize(texture->GetFormat());
uint32_t rowSize = textureLocation.width * texelSize;
d3d12Location.PlacedFootprint.Footprint.RowPitch = ((rowSize - 1) / D3D12_TEXTURE_DATA_PITCH_ALIGNMENT + 1) * D3D12_TEXTURE_DATA_PITCH_ALIGNMENT;

View File

@ -49,9 +49,9 @@ namespace d3d12 {
return backendDevice->GetCommandQueue();
}
void SetNextTexture(nxtDevice device, ComPtr<ID3D12Resource> resource, ComPtr<ID3D12Resource> depthResource) {
void SetNextTexture(nxtDevice device, ComPtr<ID3D12Resource> resource) {
Device* backendDevice = reinterpret_cast<Device*>(device);
backendDevice->SetNextTexture(resource, depthResource);
backendDevice->SetNextTexture(resource);
}
uint64_t GetSerial(const nxtDevice device) {
@ -160,14 +160,10 @@ namespace d3d12 {
return nextTexture;
}
ComPtr<ID3D12Resource> Device::GetCurrentDepthTexture() {
return nextDepthTexture;
void Device::SetNextTexture(ComPtr<ID3D12Resource> resource) {
nextTexture = resource;
}
void Device::SetNextTexture(ComPtr<ID3D12Resource> resource, ComPtr<ID3D12Resource> depthResource) {
nextTexture = resource;
nextDepthTexture = depthResource;
}
void Device::TickImpl() {
// Perform cleanup operations to free unused objects

View File

@ -124,8 +124,7 @@ namespace d3d12 {
ComPtr<ID3D12GraphicsCommandList> GetPendingCommandList();
ComPtr<ID3D12Resource> GetCurrentTexture();
ComPtr<ID3D12Resource> GetCurrentDepthTexture();
void SetNextTexture(ComPtr<ID3D12Resource> resource, ComPtr<ID3D12Resource> depthResource);
void SetNextTexture(ComPtr<ID3D12Resource> resource);
uint64_t GetSerial() const;
void NextSerial();
@ -153,7 +152,6 @@ namespace d3d12 {
} pendingCommands;
ComPtr<ID3D12Resource> nextTexture;
ComPtr<ID3D12Resource> nextDepthTexture;
};
class DepthStencilState : public DepthStencilStateBase {

View File

@ -23,73 +23,79 @@ namespace d3d12 {
Framebuffer::Framebuffer(Device* device, FramebufferBuilder* builder)
: FramebufferBase(builder), device(device) {
RenderPass* renderPass = ToBackend(GetRenderPass());
uint32_t attachmentCount = renderPass->GetAttachmentCount();
rtvHeap = device->GetDescriptorHeapAllocator()->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, attachmentCount);
bool usingBackbuffer = false; // HACK(enga@google.com): workaround for not having depth attachments
uint32_t rtvIndex = 0;
for (uint32_t attachment = 0; attachment < attachmentCount; ++attachment) {
uint32_t rtvCount = 0, dsvCount = 0;
attachmentHeapIndices.resize(renderPass->GetAttachmentCount());
for (uint32_t attachment = 0; attachment < renderPass->GetAttachmentCount(); ++attachment) {
auto* textureView = GetTextureView(attachment);
if (textureView) {
ComPtr<ID3D12Resource> texture = ToBackend(textureView->GetTexture())->GetD3D12Resource();
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(rtvIndex++);
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = ToBackend(textureView)->GetRTVDescriptor();
device->GetD3D12Device()->CreateRenderTargetView(texture.Get(), &rtvDesc, rtvHandle);
if (!textureView) {
// TODO(kainino@chromium.org): null=backbuffer hack
attachmentHeapIndices[attachment] = rtvCount++;
continue;
}
auto format = textureView->GetTexture()->GetFormat();
if (TextureFormatHasDepth(format) || TextureFormatHasStencil(format)) {
attachmentHeapIndices[attachment] = dsvCount++;
} else {
// TODO(enga@google.com) no attachment. This will use the backbuffer. Remove when this hack is removed
usingBackbuffer = true;
rtvIndex++;
attachmentHeapIndices[attachment] = rtvCount++;
}
}
// TODO(enga@google.com): load depth attachment from subpass
if (usingBackbuffer) {
dsvHeap = device->GetDescriptorHeapAllocator()->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1);
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap.GetCPUHandle(0);
if (rtvCount) {
rtvHeap = device->GetDescriptorHeapAllocator()->AllocateCPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE_RTV, rtvCount);
}
if (dsvCount) {
dsvHeap = device->GetDescriptorHeapAllocator()->AllocateCPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE_DSV, dsvCount);
}
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
dsvDesc.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
dsvDesc.Texture2D.MipSlice = 0;
dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
for (uint32_t attachment = 0; attachment < renderPass->GetAttachmentCount(); ++attachment) {
uint32_t heapIndex = attachmentHeapIndices[attachment];
auto* textureView = GetTextureView(attachment);
if (!textureView) {
continue;
}
device->GetD3D12Device()->CreateDepthStencilView(device->GetCurrentDepthTexture().Get(), &dsvDesc, dsvHandle);
ComPtr<ID3D12Resource> texture = ToBackend(textureView->GetTexture())->GetD3D12Resource();
auto format = textureView->GetTexture()->GetFormat();
if (TextureFormatHasDepth(format) || TextureFormatHasStencil(format)) {
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap.GetCPUHandle(heapIndex);
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = ToBackend(textureView)->GetDSVDescriptor();
device->GetD3D12Device()->CreateDepthStencilView(texture.Get(), &dsvDesc, dsvHandle);
} else {
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(heapIndex);
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = ToBackend(textureView)->GetRTVDescriptor();
device->GetD3D12Device()->CreateRenderTargetView(texture.Get(), &rtvDesc, rtvHandle);
}
}
}
Framebuffer::OMSetRenderTargetArgs Framebuffer::GetSubpassOMSetRenderTargetArgs(uint32_t subpassIndex) {
const auto& subpassInfo = GetRenderPass()->GetSubpassInfo(subpassIndex);
bool usingBackbuffer = false; // HACK(enga@google.com): workaround for not having depth attachments
OMSetRenderTargetArgs args;
args.numRTVs = 0;
OMSetRenderTargetArgs args = {};
for (uint32_t index : IterateBitSet(subpassInfo.colorAttachmentsSet)) {
uint32_t heapIndex = attachmentHeapIndices[subpassInfo.colorAttachments[index]];
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(heapIndex);
uint32_t attachment = subpassInfo.colorAttachments[index];
const auto& attachmentInfo = GetRenderPass()->GetAttachmentInfo(attachment);
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(attachment);
args.RTVs[args.numRTVs++] = rtvHandle;
if (!GetTextureView(attachment)) {
usingBackbuffer = true;
// TODO(kainino@chromium.org): null=backbuffer hack
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = D3D12TextureFormat(attachmentInfo.format);
rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = 0;
rtvDesc.Texture2D.PlaneSlice = 0;
device->GetD3D12Device()->CreateRenderTargetView(device->GetCurrentTexture().Get(), &rtvDesc, rtvHandle);
}
}
if (usingBackbuffer) {
args.dsv = dsvHeap.GetCPUHandle(0);
args.RTVs[args.numRTVs++] = rtvHandle;
}
if (subpassInfo.depthStencilAttachmentSet) {
uint32_t heapIndex = attachmentHeapIndices[subpassInfo.depthStencilAttachment];
args.dsv = dsvHeap.GetCPUHandle(heapIndex);
}
return args;

View File

@ -21,6 +21,8 @@
#include "backend/d3d12/d3d12_platform.h"
#include "backend/d3d12/DescriptorHeapAllocator.h"
#include <vector>
namespace backend {
namespace d3d12 {
@ -29,9 +31,9 @@ namespace d3d12 {
class Framebuffer : public FramebufferBase {
public:
struct OMSetRenderTargetArgs {
unsigned int numRTVs;
unsigned int numRTVs = 0;
D3D12_CPU_DESCRIPTOR_HANDLE RTVs[kMaxColorAttachments] = {};
D3D12_CPU_DESCRIPTOR_HANDLE dsv = { 0 };
D3D12_CPU_DESCRIPTOR_HANDLE dsv = {};
};
Framebuffer(Device* device, FramebufferBuilder* builder);
@ -41,6 +43,9 @@ namespace d3d12 {
Device* device;
DescriptorHeapHandle rtvHeap;
DescriptorHeapHandle dsvHeap;
// Indices into either the RTV or DSV heap, depending on texture format.
std::vector<uint32_t> attachmentHeapIndices;
};
}

View File

@ -37,9 +37,10 @@ namespace d3d12 {
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
}
if (usage & nxt::TextureUsageBit::OutputAttachment) {
resourceState |= D3D12_RESOURCE_STATE_RENDER_TARGET;
if (TextureBase::IsDepthFormat(format)) {
if (TextureFormatHasDepth(format) || TextureFormatHasStencil(format)) {
resourceState |= D3D12_RESOURCE_STATE_DEPTH_WRITE;
} else {
resourceState |= D3D12_RESOURCE_STATE_RENDER_TARGET;
}
}
@ -53,12 +54,15 @@ namespace d3d12 {
flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
}
if (usage & nxt::TextureUsageBit::OutputAttachment) {
flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
if (TextureBase::IsDepthFormat(format)) {
if (TextureFormatHasDepth(format) || TextureFormatHasStencil(format)) {
flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
} else {
flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
}
}
ASSERT(!(flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) ||
flags == D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);
return flags;
}
@ -77,6 +81,8 @@ namespace d3d12 {
switch (format) {
case nxt::TextureFormat::R8G8B8A8Unorm:
return DXGI_FORMAT_R8G8B8A8_UNORM;
case nxt::TextureFormat::D32FloatS8Uint:
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
default:
UNREACHABLE();
}
@ -96,7 +102,7 @@ namespace d3d12 {
resourceDescriptor.SampleDesc.Count = 1;
resourceDescriptor.SampleDesc.Quality = 0;
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resourceDescriptor.Flags = D3D12ResourceFlags(GetUsage(), GetFormat());
resourceDescriptor.Flags = D3D12ResourceFlags(GetAllowedUsage(), GetFormat());
resource = device->GetResourceAllocator()->Allocate(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor, D3D12TextureUsage(GetUsage(), GetFormat()));
}
@ -167,5 +173,14 @@ namespace d3d12 {
return rtvDesc;
}
D3D12_DEPTH_STENCIL_VIEW_DESC TextureView::GetDSVDescriptor() {
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
dsvDesc.Format = ToBackend(GetTexture())->GetD3D12Format();
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
dsvDesc.Texture2D.MipSlice = 0;
dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
return dsvDesc;
}
}
}

View File

@ -49,6 +49,7 @@ namespace d3d12 {
const D3D12_SHADER_RESOURCE_VIEW_DESC& GetSRVDescriptor() const;
D3D12_RENDER_TARGET_VIEW_DESC GetRTVDescriptor();
D3D12_DEPTH_STENCIL_VIEW_DESC GetDSVDescriptor();
private:
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;

View File

@ -86,7 +86,6 @@ namespace metal {
const auto& info = currentRenderPass->GetSubpassInfo(subpass);
MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
bool usingBackbuffer = false; // HACK(kainino@chromium.org): workaround for not having depth attachments
for (uint32_t index = 0; index < info.colorAttachments.size(); ++index) {
uint32_t attachment = info.colorAttachments[index];
@ -98,18 +97,30 @@ namespace metal {
texture = ToBackend(textureView->GetTexture())->GetMTLTexture();
} else {
texture = device->GetCurrentTexture();
usingBackbuffer = true;
}
descriptor.colorAttachments[index].texture = texture;
descriptor.colorAttachments[index].loadAction = MTLLoadActionClear;
descriptor.colorAttachments[index].loadAction = MTLLoadActionLoad;
descriptor.colorAttachments[index].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 0.0);
descriptor.colorAttachments[index].storeAction = MTLStoreActionStore;
}
// TODO(kainino@chromium.org): load depth attachment from subpass
if (usingBackbuffer) {
descriptor.depthAttachment.texture = device->GetCurrentDepthTexture();
descriptor.depthAttachment.loadAction = MTLLoadActionLoad;
descriptor.depthAttachment.storeAction = MTLStoreActionStore;
if (info.depthStencilAttachmentSet) {
uint32_t attachment = info.depthStencilAttachment;
auto textureView = currentFramebuffer->GetTextureView(attachment);
id<MTLTexture> texture = ToBackend(textureView->GetTexture())->GetMTLTexture();
nxt::TextureFormat format = textureView->GetTexture()->GetFormat();
if (TextureFormatHasDepth(format)) {
descriptor.depthAttachment.texture = texture;
descriptor.depthAttachment.loadAction = MTLLoadActionClear;
descriptor.depthAttachment.clearDepth = 1.0;
descriptor.depthAttachment.storeAction = MTLStoreActionStore;
}
if (TextureFormatHasStencil(format)) {
descriptor.stencilAttachment.texture = texture;
descriptor.stencilAttachment.loadAction = MTLLoadActionClear;
descriptor.stencilAttachment.clearStencil = 0;
descriptor.stencilAttachment.storeAction = MTLStoreActionStore;
}
}
render = [commandBuffer renderCommandEncoderWithDescriptor:descriptor];

View File

@ -108,7 +108,6 @@ namespace metal {
id<MTLDevice> GetMTLDevice();
id<MTLTexture> GetCurrentTexture();
id<MTLTexture> GetCurrentDepthTexture();
id<MTLCommandBuffer> GetPendingCommandBuffer();
void SubmitPendingCommandBuffer();
@ -127,7 +126,6 @@ namespace metal {
id<CAMetalDrawable> currentDrawable = nil;
id<MTLTexture> currentTexture = nil;
id<MTLTexture> currentDepthTexture = nil;
Serial finishedCommandSerial = 0;
Serial pendingCommandSerial = 1;

View File

@ -74,9 +74,6 @@ namespace metal {
[currentTexture release];
currentTexture = nil;
[currentDepthTexture release];
currentDepthTexture = nil;
}
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
@ -146,32 +143,11 @@ namespace metal {
currentTexture = drawable.texture;
[currentTexture retain];
if (currentDepthTexture == nil ||
currentTexture.width != currentDepthTexture.width ||
currentTexture.height != currentDepthTexture.height) {
if (currentDepthTexture != nil) {
[currentDepthTexture release];
}
MTLTextureDescriptor* depthDescriptor = [MTLTextureDescriptor
texture2DDescriptorWithPixelFormat:MTLPixelFormatDepth32Float
width:currentTexture.width
height:currentTexture.height
mipmapped:NO];
depthDescriptor.textureType = MTLTextureType2D;
depthDescriptor.usage = MTLTextureUsageRenderTarget;
depthDescriptor.storageMode = MTLStorageModePrivate;
currentDepthTexture = [mtlDevice newTextureWithDescriptor:depthDescriptor];
}
MTLRenderPassDescriptor* passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
passDescriptor.colorAttachments[0].texture = currentTexture;
passDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
passDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
passDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0);
passDescriptor.depthAttachment.texture = currentDepthTexture;
passDescriptor.depthAttachment.loadAction = MTLLoadActionClear;
passDescriptor.depthAttachment.storeAction = MTLStoreActionStore;
passDescriptor.depthAttachment.clearDepth = 1.0;
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
@ -195,10 +171,6 @@ namespace metal {
return currentTexture;
}
id<MTLTexture> Device::GetCurrentDepthTexture() {
return currentDepthTexture;
}
id<MTLCommandBuffer> Device::GetPendingCommandBuffer() {
if (pendingCommands == nil) {
pendingCommands = [commandQueue commandBuffer];

View File

@ -24,6 +24,8 @@ namespace metal {
switch (format) {
case nxt::TextureFormat::R8G8B8A8Unorm:
return MTLPixelFormatRGBA8Unorm;
case nxt::TextureFormat::D32FloatS8Uint:
return MTLPixelFormatDepth32Float_Stencil8;
}
}
@ -65,6 +67,7 @@ namespace metal {
desc.depth = GetDepth();
desc.mipmapLevelCount = GetNumMipLevels();
desc.arrayLength = 1;
desc.storageMode = MTLStorageModePrivate;
auto mtlDevice = ToBackend(builder->GetDevice())->GetMTLDevice();
mtlTexture = [mtlDevice newTextureWithDescriptor:desc];

View File

@ -103,7 +103,6 @@ namespace opengl {
auto* device = ToBackend(GetDevice());
const auto& info = currentRenderPass->GetSubpassInfo(currentSubpass);
bool usingBackbuffer = false; // HACK(kainino@chromium.org): workaround for not having depth attachments
for (uint32_t index = 0; index < info.colorAttachments.size(); ++index) {
uint32_t attachment = info.colorAttachments[index];
@ -115,16 +114,35 @@ namespace opengl {
texture = ToBackend(textureView->GetTexture())->GetHandle();
} else {
texture = device->GetCurrentTexture();
usingBackbuffer = true;
}
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + index,
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0 + index,
GL_TEXTURE_2D, texture, 0);
}
// TODO(kainino@chromium.org): load depth attachment from subpass
if (usingBackbuffer) {
GLuint texture = device->GetCurrentDepthTexture();
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D, texture, 0);
if (info.depthStencilAttachmentSet) {
uint32_t attachment = info.depthStencilAttachment;
auto textureView = currentFramebuffer->GetTextureView(attachment);
GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
nxt::TextureFormat format = textureView->GetTexture()->GetFormat();
GLenum glAttachment = 0;
if (TextureFormatHasDepth(format)) {
if (TextureFormatHasStencil(format)) {
glAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
} else {
glAttachment = GL_DEPTH_ATTACHMENT;
}
} else {
glAttachment = GL_STENCIL_ATTACHMENT;
}
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
glAttachment, GL_TEXTURE_2D, texture, 0);
// Load action
glClearStencil(0);
glClearDepth(1.0);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
}
break;

View File

@ -111,9 +111,7 @@ namespace opengl {
void Device::HACKCLEAR() {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, backFBO);
glClearColor(0, 0, 0, 1);
glStencilMask(0xff);
glClearStencil(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT);
}
void Device::InitBackbuffer() {
@ -121,16 +119,10 @@ namespace opengl {
glBindTexture(GL_TEXTURE_2D, backTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 640, 480, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glGenTextures(1, &backDepthTexture);
glBindTexture(GL_TEXTURE_2D, backDepthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 640, 480, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
glGenFramebuffers(1, &backFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER, backFBO);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, backTexture, 0);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D, backDepthTexture, 0);
HACKCLEAR();
}
@ -146,10 +138,6 @@ namespace opengl {
return backTexture;
}
GLuint Device::GetCurrentDepthTexture() {
return backDepthTexture;
}
// Bind Group
BindGroup::BindGroup(BindGroupBuilder* builder)

View File

@ -103,12 +103,10 @@ namespace opengl {
void InitBackbuffer();
void CommitBackbuffer();
GLuint GetCurrentTexture();
GLuint GetCurrentDepthTexture();
private:
GLuint backFBO = 0;
GLuint backTexture = 0;
GLuint backDepthTexture = 0;
};
class BindGroup : public BindGroupBase {

View File

@ -37,6 +37,8 @@ namespace opengl {
switch (format) {
case nxt::TextureFormat::R8G8B8A8Unorm:
return {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE};
case nxt::TextureFormat::D32FloatS8Uint:
return {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV};
default:
UNREACHABLE();
}

View File

@ -31,7 +31,7 @@ namespace backend {
namespace d3d12 {
void Init(ComPtr<ID3D12Device> d3d12Device, nxtProcTable* procs, nxtDevice* device);
ComPtr<ID3D12CommandQueue> GetCommandQueue(nxtDevice device);
void SetNextTexture(nxtDevice device, ComPtr<ID3D12Resource> resource, ComPtr<ID3D12Resource> depthResource);
void SetNextTexture(nxtDevice device, ComPtr<ID3D12Resource> resource);
uint64_t GetSerial(const nxtDevice device);
void NextSerial(nxtDevice device);
void ExecuteCommandLists(nxtDevice device, std::initializer_list<ID3D12CommandList*> commandLists);
@ -100,44 +100,9 @@ namespace utils {
&swapChain1
));
ASSERT_SUCCESS(swapChain1.As(&swapChain));
// Create a render target and depth stencil resource for each frame.
{
D3D12_HEAP_PROPERTIES dsvHeapProperties;
dsvHeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
dsvHeapProperties.CreationNodeMask = 0;
dsvHeapProperties.VisibleNodeMask = 0;
dsvHeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
dsvHeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
D3D12_RESOURCE_DESC dsvDesc;
dsvDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
dsvDesc.Alignment = 0;
dsvDesc.Width = width;
dsvDesc.Height = height;
dsvDesc.DepthOrArraySize = 1;
dsvDesc.MipLevels = 0;
dsvDesc.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
dsvDesc.SampleDesc.Count = 1;
dsvDesc.SampleDesc.Quality = 0;
dsvDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
dsvDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
D3D12_CLEAR_VALUE dsvClear;
dsvClear.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
dsvClear.DepthStencil.Depth = 1.0f;
dsvClear.DepthStencil.Stencil = 0;
for (uint32_t n = 0; n < kFrameCount; ++n) {
ASSERT_SUCCESS(swapChain->GetBuffer(n, IID_PPV_ARGS(&renderTargetResources[n])));
ASSERT_SUCCESS(d3d12Device->CreateCommittedResource(
&dsvHeapProperties,
D3D12_HEAP_FLAG_NONE,
&dsvDesc,
D3D12_RESOURCE_STATE_DEPTH_WRITE,
&dsvClear,
IID_PPV_ARGS(&depthStencilResources[n])));
}
for (uint32_t n = 0; n < kFrameCount; ++n) {
ASSERT_SUCCESS(swapChain->GetBuffer(n, IID_PPV_ARGS(&renderTargetResources[n])));
}
// Get the initial render target and arbitrarily choose a "previous" render target that's different
@ -168,7 +133,7 @@ namespace utils {
backend::d3d12::NextSerial(backendDevice);
}
backend::d3d12::SetNextTexture(backendDevice, renderTargetResources[renderTargetIndex], depthStencilResources[renderTargetIndex]);
backend::d3d12::SetNextTexture(backendDevice, renderTargetResources[renderTargetIndex]);
}
void SwapBuffers() override {
@ -217,7 +182,7 @@ namespace utils {
lastSerialRenderTargetWasUsed[renderTargetIndex] = backend::d3d12::GetSerial(backendDevice);
// Tell the backend to render to the current render target
backend::d3d12::SetNextTexture(backendDevice, renderTargetResources[renderTargetIndex], depthStencilResources[renderTargetIndex]);
backend::d3d12::SetNextTexture(backendDevice, renderTargetResources[renderTargetIndex]);
}
private:
@ -232,7 +197,6 @@ namespace utils {
ComPtr<ID3D12CommandQueue> commandQueue;
ComPtr<IDXGISwapChain3> swapChain;
ComPtr<ID3D12Resource> renderTargetResources[kFrameCount];
ComPtr<ID3D12Resource> depthStencilResources[kFrameCount];
// Frame synchronization. Updated every frame
uint32_t renderTargetIndex;

View File

@ -88,15 +88,30 @@ namespace utils {
}
void CreateDefaultRenderPass(const nxt::Device& device, nxt::RenderPass* renderPass, nxt::Framebuffer* framebuffer) {
auto depthStencilTexture = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(640, 480, 1)
.SetFormat(nxt::TextureFormat::D32FloatS8Uint)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment)
.GetResult();
depthStencilTexture.FreezeUsage(nxt::TextureUsageBit::OutputAttachment);
auto depthStencilView = depthStencilTexture.CreateTextureViewBuilder()
.GetResult();
*renderPass = device.CreateRenderPassBuilder()
.SetAttachmentCount(1)
.SetAttachmentCount(2)
.AttachmentSetFormat(0, nxt::TextureFormat::R8G8B8A8Unorm)
.AttachmentSetFormat(1, nxt::TextureFormat::D32FloatS8Uint)
.SetSubpassCount(1)
.SubpassSetColorAttachment(0, 0, 0)
.SubpassSetDepthStencilAttachment(0, 1)
.GetResult();
*framebuffer = device.CreateFramebufferBuilder()
.SetRenderPass(*renderPass)
.SetDimensions(640, 480)
// Attachment 0 is implicit until we add WSI
.SetAttachment(1, depthStencilView)
.GetResult();
}