Update SwapChain to configure texture usage
Explicitly configure swap chain usage in bindings and examples Fix missing case in switch Make swap chain Present usage implicit Author: Austin Eng <enga@google.com>
This commit is contained in:
parent
08a0081c13
commit
ee7b6b1b62
|
@ -49,7 +49,7 @@ void init() {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
|
|
|
@ -39,7 +39,7 @@ void init() {
|
|||
swapchain = nxtSwapChainBuilderGetResult(builder);
|
||||
nxtSwapChainBuilderRelease(builder);
|
||||
}
|
||||
nxtSwapChainConfigure(swapchain, NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM, 640, 480);
|
||||
nxtSwapChainConfigure(swapchain, NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM, NXT_TEXTURE_USAGE_BIT_OUTPUT_ATTACHMENT, NXT_TEXTURE_USAGE_BIT_OUTPUT_ATTACHMENT, 640, 480);
|
||||
|
||||
const char* vs =
|
||||
"#version 450\n"
|
||||
|
|
|
@ -291,7 +291,7 @@ void init() {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
initBuffers();
|
||||
initRender();
|
||||
|
|
|
@ -35,7 +35,7 @@ void init() {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
struct {uint32_t a; float b;} s;
|
||||
memset(&s, 0, sizeof(s));
|
||||
|
|
|
@ -116,7 +116,7 @@ void init() {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
initBuffers();
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ void init() {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
initBuffers();
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ void init() {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
initBuffers();
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ void init() {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
initBuffers();
|
||||
initTextures();
|
||||
|
|
|
@ -33,7 +33,7 @@ void init() {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
nxt::ShaderModule vsModule = utils::CreateShaderModule(device, nxt::ShaderStage::Vertex, R"(
|
||||
#version 450
|
||||
|
|
|
@ -43,7 +43,7 @@ void init() {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
initBuffers();
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ void init() {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
initBuffers();
|
||||
initTextures();
|
||||
|
|
|
@ -464,7 +464,7 @@ namespace {
|
|||
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
swapchain = GetSwapChain(device);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, 640, 480);
|
||||
swapchain.Configure(nxt::TextureFormat::R8G8B8A8Unorm, nxt::TextureUsageBit::OutputAttachment, nxt::TextureUsageBit::OutputAttachment, 640, 480);
|
||||
|
||||
renderpass = CreateDefaultRenderPass(device);
|
||||
depthStencilView = CreateDefaultDepthStencilView(device);
|
||||
|
|
|
@ -1050,6 +1050,8 @@
|
|||
"name": "configure",
|
||||
"args": [
|
||||
{"name": "format", "type": "texture format"},
|
||||
{"name": "allowedUsage", "type": "texture usage bit"},
|
||||
{"name": "initialUsage", "type": "texture usage bit"},
|
||||
{"name": "width", "type": "uint32_t"},
|
||||
{"name": "height", "type": "uint32_t"}
|
||||
]
|
||||
|
|
|
@ -34,17 +34,24 @@ namespace backend {
|
|||
return device;
|
||||
}
|
||||
|
||||
void SwapChainBase::Configure(nxt::TextureFormat format, uint32_t width, uint32_t height) {
|
||||
void SwapChainBase::Configure(nxt::TextureFormat format, nxt::TextureUsageBit allowedUsage, nxt::TextureUsageBit initialUsage, uint32_t width, uint32_t height) {
|
||||
if (width == 0 || height == 0) {
|
||||
device->HandleError("Swap chain cannot be configured to zero size");
|
||||
return;
|
||||
}
|
||||
allowedUsage |= nxt::TextureUsageBit::Present;
|
||||
if (!(HasZeroOrOneBits(initialUsage) && (initialUsage & allowedUsage))) {
|
||||
device->HandleError("Swap chain configured with invalid texture usage");
|
||||
return;
|
||||
}
|
||||
|
||||
this->format = format;
|
||||
this->allowedUsage = allowedUsage;
|
||||
this->initialUsage = initialUsage;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
implementation.Configure(implementation.userData,
|
||||
static_cast<nxtTextureFormat>(format), width, height);
|
||||
static_cast<nxtTextureFormat>(format), static_cast<nxtTextureUsageBit>(allowedUsage), static_cast<nxtTextureUsageBit>(initialUsage), width, height);
|
||||
}
|
||||
|
||||
TextureBase* SwapChainBase::GetNextTexture() {
|
||||
|
@ -59,8 +66,8 @@ namespace backend {
|
|||
builder->SetExtent(width, height, 1);
|
||||
builder->SetFormat(format);
|
||||
builder->SetMipLevels(1);
|
||||
builder->SetAllowedUsage(nxt::TextureUsageBit::OutputAttachment | nxt::TextureUsageBit::Present);
|
||||
builder->SetInitialUsage(nxt::TextureUsageBit::OutputAttachment);
|
||||
builder->SetAllowedUsage(allowedUsage);
|
||||
builder->SetInitialUsage(initialUsage);
|
||||
|
||||
auto* texture = GetNextTextureImpl(builder);
|
||||
lastNextTexture = texture;
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace backend {
|
|||
DeviceBase* GetDevice();
|
||||
|
||||
// NXT API
|
||||
void Configure(nxt::TextureFormat format, uint32_t width, uint32_t height);
|
||||
void Configure(nxt::TextureFormat format, nxt::TextureUsageBit allowedUsage, nxt::TextureUsageBit initialUsage, uint32_t width, uint32_t height);
|
||||
TextureBase* GetNextTexture();
|
||||
void Present(TextureBase* texture);
|
||||
|
||||
|
@ -44,6 +44,8 @@ namespace backend {
|
|||
DeviceBase* device = nullptr;
|
||||
nxtSwapChainImplementation implementation = {};
|
||||
nxt::TextureFormat format = {};
|
||||
nxt::TextureUsageBit allowedUsage;
|
||||
nxt::TextureUsageBit initialUsage;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
TextureBase* lastNextTexture = nullptr;
|
||||
|
|
|
@ -58,6 +58,7 @@ namespace backend {
|
|||
bool TextureFormatHasDepthOrStencil(nxt::TextureFormat format) {
|
||||
switch (format) {
|
||||
case nxt::TextureFormat::R8G8B8A8Unorm:
|
||||
case nxt::TextureFormat::R8G8B8A8Uint:
|
||||
return false;
|
||||
case nxt::TextureFormat::D32FloatS8Uint:
|
||||
return true;
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace opengl {
|
|||
switch (format) {
|
||||
case nxt::TextureFormat::R8G8B8A8Unorm:
|
||||
return {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE};
|
||||
case nxt::TextureFormat::R8G8B8A8Uint:
|
||||
return { GL_RGBA8UI, GL_RGBA, GL_UNSIGNED_INT };
|
||||
case nxt::TextureFormat::D32FloatS8Uint:
|
||||
return {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV};
|
||||
default:
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef struct {
|
|||
void (*Destroy)(void* userData);
|
||||
|
||||
/// Configure/reconfigure the swap chain.
|
||||
nxtSwapChainError (*Configure)(void* userData, nxtTextureFormat format, uint32_t width, uint32_t height);
|
||||
nxtSwapChainError (*Configure)(void* userData, nxtTextureFormat format, nxtTextureUsageBit allowedUsage, nxtTextureUsageBit initialUsage, uint32_t width, uint32_t height);
|
||||
|
||||
/// Acquire the next texture from the swap chain.
|
||||
nxtSwapChainError (*GetNextTexture)(void* userData, nxtSwapChainNextTexture* nextTexture);
|
||||
|
|
|
@ -77,6 +77,41 @@ namespace utils {
|
|||
|
||||
return factory;
|
||||
}
|
||||
|
||||
DXGI_USAGE D3D12SwapChainBufferUsage(nxtTextureUsageBit allowedUsages) {
|
||||
DXGI_USAGE usage = DXGI_CPU_ACCESS_NONE;
|
||||
if (allowedUsages & NXT_TEXTURE_USAGE_BIT_SAMPLED) {
|
||||
usage |= DXGI_USAGE_SHADER_INPUT;
|
||||
}
|
||||
if (allowedUsages & NXT_TEXTURE_USAGE_BIT_STORAGE) {
|
||||
usage |= DXGI_USAGE_UNORDERED_ACCESS;
|
||||
}
|
||||
if (allowedUsages & NXT_TEXTURE_USAGE_BIT_OUTPUT_ATTACHMENT) {
|
||||
usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_STATES D3D12ResourceState(nxtTextureUsageBit usage) {
|
||||
D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_COMMON;
|
||||
if (usage & NXT_TEXTURE_USAGE_BIT_TRANSFER_SRC) {
|
||||
resourceState |= D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
}
|
||||
if (usage & NXT_TEXTURE_USAGE_BIT_TRANSFER_DST) {
|
||||
resourceState |= D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
}
|
||||
if (usage & NXT_TEXTURE_USAGE_BIT_SAMPLED) {
|
||||
resourceState |= (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||
}
|
||||
if (usage & NXT_TEXTURE_USAGE_BIT_STORAGE) {
|
||||
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
}
|
||||
if (usage & NXT_TEXTURE_USAGE_BIT_OUTPUT_ATTACHMENT) {
|
||||
resourceState |= D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
}
|
||||
|
||||
return resourceState;
|
||||
}
|
||||
}
|
||||
|
||||
class SwapChainImplD3D12 : SwapChainImpl {
|
||||
|
@ -104,6 +139,8 @@ namespace utils {
|
|||
uint32_t previousRenderTargetIndex = 0;
|
||||
uint64_t lastSerialRenderTargetWasUsed[kFrameCount] = {};
|
||||
|
||||
D3D12_RESOURCE_STATES renderTargetResourceState;
|
||||
|
||||
SwapChainImplD3D12(HWND window, nxtProcTable procs)
|
||||
: window(window), procs(procs), factory(CreateFactory()) {
|
||||
}
|
||||
|
@ -119,7 +156,7 @@ namespace utils {
|
|||
commandQueue = backend::d3d12::GetCommandQueue(backendDevice);
|
||||
}
|
||||
|
||||
nxtSwapChainError Configure(nxtTextureFormat format,
|
||||
nxtSwapChainError Configure(nxtTextureFormat format, nxtTextureUsageBit allowedUsage, nxtTextureUsageBit initialUsage,
|
||||
uint32_t width, uint32_t height) {
|
||||
if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) {
|
||||
return "unsupported format";
|
||||
|
@ -131,7 +168,7 @@ namespace utils {
|
|||
swapChainDesc.Width = width;
|
||||
swapChainDesc.Height = height;
|
||||
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.BufferUsage = D3D12SwapChainBufferUsage(allowedUsage);
|
||||
swapChainDesc.BufferCount = kFrameCount;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
|
@ -162,6 +199,25 @@ namespace utils {
|
|||
lastSerialRenderTargetWasUsed[n] = initialSerial;
|
||||
}
|
||||
|
||||
renderTargetResourceState = D3D12ResourceState(initialUsage);
|
||||
|
||||
// Transition the first frame. Resources are initially created in PRESENT state
|
||||
if (renderTargetResourceState != D3D12_RESOURCE_STATE_PRESENT) {
|
||||
ComPtr<ID3D12GraphicsCommandList> commandList = {};
|
||||
backend::d3d12::OpenCommandList(backendDevice, &commandList);
|
||||
|
||||
D3D12_RESOURCE_BARRIER resourceBarrier;
|
||||
resourceBarrier.Transition.pResource = renderTargetResources[renderTargetIndex].Get();
|
||||
resourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
resourceBarrier.Transition.StateAfter = renderTargetResourceState;
|
||||
resourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
commandList->ResourceBarrier(1, &resourceBarrier);
|
||||
ASSERT_SUCCESS(commandList->Close());
|
||||
backend::d3d12::ExecuteCommandLists(backendDevice, { commandList.Get() });
|
||||
}
|
||||
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -178,14 +234,14 @@ namespace utils {
|
|||
ASSERT_SUCCESS(swapChain->Present(1, 0));
|
||||
|
||||
// Transition last frame's render target back to being a render target
|
||||
{
|
||||
if (renderTargetResourceState != D3D12_RESOURCE_STATE_PRESENT) {
|
||||
ComPtr<ID3D12GraphicsCommandList> commandList = {};
|
||||
backend::d3d12::OpenCommandList(backendDevice, &commandList);
|
||||
|
||||
D3D12_RESOURCE_BARRIER resourceBarrier;
|
||||
resourceBarrier.Transition.pResource = renderTargetResources[previousRenderTargetIndex].Get();
|
||||
resourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
resourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
resourceBarrier.Transition.StateAfter = renderTargetResourceState;
|
||||
resourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace utils {
|
|||
commandQueue = [mtlDevice newCommandQueue];
|
||||
}
|
||||
|
||||
nxtSwapChainError Configure(nxtTextureFormat format,
|
||||
nxtSwapChainError Configure(nxtTextureFormat format, nxtTextureUsageBit, nxtTextureUsageBit,
|
||||
uint32_t width, uint32_t height) {
|
||||
if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) {
|
||||
return "unsupported format";
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace utils {
|
|||
GL_TEXTURE_2D, backTexture, 0);
|
||||
}
|
||||
|
||||
nxtSwapChainError Configure(nxtTextureFormat format,
|
||||
nxtSwapChainError Configure(nxtTextureFormat format, nxtTextureUsageBit, nxtTextureUsageBit,
|
||||
uint32_t width, uint32_t height) {
|
||||
if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) {
|
||||
return "unsupported format";
|
||||
|
|
|
@ -28,9 +28,9 @@ namespace utils {
|
|||
impl.Destroy = [](void* userData) {
|
||||
delete reinterpret_cast<TImpl*>(userData);
|
||||
};
|
||||
impl.Configure = [](void* userData, nxtTextureFormat format, uint32_t width, uint32_t height) {
|
||||
impl.Configure = [](void* userData, nxtTextureFormat format, nxtTextureUsageBit allowedUsage, nxtTextureUsageBit initialUsage, uint32_t width, uint32_t height) {
|
||||
return reinterpret_cast<TImpl*>(userData)->Configure(
|
||||
format, width, height);
|
||||
format, allowedUsage, initialUsage, width, height);
|
||||
};
|
||||
impl.GetNextTexture = [](void* userData, nxtSwapChainNextTexture* nextTexture) {
|
||||
return reinterpret_cast<TImpl*>(userData)->GetNextTexture(
|
||||
|
|
Loading…
Reference in New Issue