Format: src/{common, utils, wire}

This commit is contained in:
Corentin Wallez 2017-11-24 11:45:29 -05:00 committed by Corentin Wallez
parent a351ce9618
commit 9d01c6c26d
29 changed files with 897 additions and 876 deletions

View File

@ -16,7 +16,11 @@
#include <iostream> #include <iostream>
void HandleAssertionFailure(const char* file, const char* function, int line, const char* condition) { void HandleAssertionFailure(const char* file,
std::cerr << "Assertion failure at " << file << ":" << line << " (" << function << "): " << condition << std::endl; const char* function,
int line,
const char* condition) {
std::cerr << "Assertion failure at " << file << ":" << line << " (" << function
<< "): " << condition << std::endl;
NXT_BREAKPOINT(); NXT_BREAKPOINT();
} }

View File

@ -17,24 +17,20 @@
#include "common/Compiler.h" #include "common/Compiler.h"
void HandleAssertionFailure(const char* file, const char* function, int line, const char* condition); // NXT asserts to be used instead of the regular C stdlib assert function (if you don't use assert
// yet, you should start now!). In debug ASSERT(condition) will trigger an error, otherwise in
// release it does nothing at runtime.
//
// In case of name clashes (with for example a testing library), you can define the
// NXT_SKIP_ASSERT_SHORTHANDS to only define the NXT_ prefixed macros.
//
// These asserts feature:
// - Logging of the error with file, line and function information.
// - Breaking in the debugger when an assert is triggered and a debugger is attached.
// - Use the assert information to help the compiler optimizer in release builds.
/* // MSVC triggers a warning in /W4 for do {} while(0). SDL worked around this by using (0,0) and
* NXT asserts to be used instead of the regular C stdlib assert function (if you don't // points out that it looks like an owl face.
* use assert yet, you should start now!). In debug ASSERT(condition) will trigger an error,
* otherwise in release it does nothing at runtime.
*
* In case of name clashes (with for example a testing library), you can define the
* NXT_SKIP_ASSERT_SHORTHANDS to only define the NXT_ prefixed macros.
*
* These asserts feature:
* - Logging of the error with file, line and function information.
* - Breaking in the debugger when an assert is triggered and a debugger is attached.
* - Use the assert information to help the compiler optimizer in release builds.
*/
// MSVC triggers a warning in /W4 for do {} while(0). SDL worked around this by using
// // (0,0) and points out that it looks like an owl face.
#if defined(NXT_COMPILER_MSVC) #if defined(NXT_COMPILER_MSVC)
# define NXT_ASSERT_LOOP_CONDITION (0, 0) # define NXT_ASSERT_LOOP_CONDITION (0, 0)
#else #else
@ -42,7 +38,8 @@ void HandleAssertionFailure(const char* file, const char* function, int line, co
#endif #endif
// NXT_ASSERT_CALLSITE_HELPER generates the actual assert code. In Debug it does what you would // NXT_ASSERT_CALLSITE_HELPER generates the actual assert code. In Debug it does what you would
// expect of an assert and in release it tries to give hints to make the compiler generate better code. // expect of an assert and in release it tries to give hints to make the compiler generate better
// code.
#if defined(NXT_ENABLE_ASSERTS) #if defined(NXT_ENABLE_ASSERTS)
# define NXT_ASSERT_CALLSITE_HELPER(file, func, line, condition) \ # define NXT_ASSERT_CALLSITE_HELPER(file, func, line, condition) \
do { \ do { \
@ -52,11 +49,9 @@ void HandleAssertionFailure(const char* file, const char* function, int line, co
} while (NXT_ASSERT_LOOP_CONDITION) } while (NXT_ASSERT_LOOP_CONDITION)
#else #else
# if defined(NXT_COMPILER_MSVC) # if defined(NXT_COMPILER_MSVC)
#define NXT_ASSERT_CALLSITE_HELPER(file, func, line, condition) \ # define NXT_ASSERT_CALLSITE_HELPER(file, func, line, condition) __assume(condition)
__assume(condition)
# elif defined(NXT_COMPILER_CLANG) && defined(__builtin_assume) # elif defined(NXT_COMPILER_CLANG) && defined(__builtin_assume)
#define NXT_ASSERT_CALLSITE_HELPER(file, func, line, condition) \ # define NXT_ASSERT_CALLSITE_HELPER(file, func, line, condition) __builtin_assume(condition)
__builtin_assume(condition)
# else # else
# define NXT_ASSERT_CALLSITE_HELPER(file, func, line, condition) \ # define NXT_ASSERT_CALLSITE_HELPER(file, func, line, condition) \
do { \ do { \
@ -68,7 +63,8 @@ void HandleAssertionFailure(const char* file, const char* function, int line, co
#define NXT_ASSERT(condition) NXT_ASSERT_CALLSITE_HELPER(__FILE__, __func__, __LINE__, condition) #define NXT_ASSERT(condition) NXT_ASSERT_CALLSITE_HELPER(__FILE__, __func__, __LINE__, condition)
#define NXT_UNREACHABLE() \ #define NXT_UNREACHABLE() \
do { \ do { \
NXT_ASSERT(NXT_ASSERT_LOOP_CONDITION && "Unreachable code hit"); NXT_BUILTIN_UNREACHABLE(); \ NXT_ASSERT(NXT_ASSERT_LOOP_CONDITION && "Unreachable code hit"); \
NXT_BUILTIN_UNREACHABLE(); \
} while (NXT_ASSERT_LOOP_CONDITION) } while (NXT_ASSERT_LOOP_CONDITION)
#if !defined(NXT_SKIP_ASSERT_SHORTHANDS) #if !defined(NXT_SKIP_ASSERT_SHORTHANDS)
@ -76,4 +72,9 @@ void HandleAssertionFailure(const char* file, const char* function, int line, co
# define UNREACHABLE NXT_UNREACHABLE # define UNREACHABLE NXT_UNREACHABLE
#endif #endif
void HandleAssertionFailure(const char* file,
const char* function,
int line,
const char* condition);
#endif // COMMON_ASSERT_H_ #endif // COMMON_ASSERT_H_

View File

@ -21,7 +21,6 @@
#include <bitset> #include <bitset>
#include <limits> #include <limits>
// This is ANGLE's BitSetIterator class with a customizable return type // This is ANGLE's BitSetIterator class with a customizable return type
// TODO(cwallez@chromium.org): it could be optimized, in particular when N <= 64 // TODO(cwallez@chromium.org): it could be optimized, in particular when N <= 64
@ -45,7 +44,9 @@ class BitSetIterator final {
bool operator==(const Iterator& other) const; bool operator==(const Iterator& other) const;
bool operator!=(const Iterator& other) const; bool operator!=(const Iterator& other) const;
T operator*() const { return static_cast<T>(mCurrentBit); } T operator*() const {
return static_cast<T>(mCurrentBit);
}
private: private:
unsigned long getNextBit(); unsigned long getNextBit();
@ -56,21 +57,23 @@ class BitSetIterator final {
unsigned long mOffset; unsigned long mOffset;
}; };
Iterator begin() const { return Iterator(mBits); } Iterator begin() const {
Iterator end() const { return Iterator(std::bitset<N>(0)); } return Iterator(mBits);
}
Iterator end() const {
return Iterator(std::bitset<N>(0));
}
private: private:
const std::bitset<N> mBits; const std::bitset<N> mBits;
}; };
template <size_t N, typename T> template <size_t N, typename T>
BitSetIterator<N, T>::BitSetIterator(const std::bitset<N>& bitset) BitSetIterator<N, T>::BitSetIterator(const std::bitset<N>& bitset) : mBits(bitset) {
: mBits(bitset) {
} }
template <size_t N, typename T> template <size_t N, typename T>
BitSetIterator<N, T>::BitSetIterator(const BitSetIterator& other) BitSetIterator<N, T>::BitSetIterator(const BitSetIterator& other) : mBits(other.mBits) {
: mBits(other.mBits) {
} }
template <size_t N, typename T> template <size_t N, typename T>

View File

@ -21,7 +21,7 @@
// - NXT_BUILTIN_UNREACHABLE(): Hints the compiler that a code path is unreachable // - NXT_BUILTIN_UNREACHABLE(): Hints the compiler that a code path is unreachable
// Clang and GCC // Clang and GCC
#ifdef __GNUC__ #if defined(__GNUC__)
# if defined(__clang__) # if defined(__clang__)
# define NXT_COMPILER_CLANG # define NXT_COMPILER_CLANG
# else # else

View File

@ -19,7 +19,8 @@
static constexpr uint32_t kMaxPushConstants = 32u; static constexpr uint32_t kMaxPushConstants = 32u;
static constexpr uint32_t kMaxBindGroups = 4u; static constexpr uint32_t kMaxBindGroups = 4u;
static constexpr uint32_t kMaxBindingsPerGroup = 16u; // TODO(cwallez@chromium.org): investigate bindgroup limits // TODO(cwallez@chromium.org): investigate bindgroup limits
static constexpr uint32_t kMaxBindingsPerGroup = 16u;
static constexpr uint32_t kMaxVertexAttributes = 16u; static constexpr uint32_t kMaxVertexAttributes = 16u;
static constexpr uint32_t kMaxVertexInputs = 16u; static constexpr uint32_t kMaxVertexInputs = 16u;
static constexpr uint32_t kNumStages = 3; static constexpr uint32_t kNumStages = 3;

View File

@ -58,7 +58,8 @@ bool IsPtrAligned(const void* ptr, size_t alignment) {
void* AlignVoidPtr(void* ptr, size_t alignment) { void* AlignVoidPtr(void* ptr, size_t alignment) {
ASSERT(IsPowerOfTwo(alignment)); ASSERT(IsPowerOfTwo(alignment));
ASSERT(alignment != 0); ASSERT(alignment != 0);
return reinterpret_cast<void*>((reinterpret_cast<size_t>(ptr) + (alignment - 1)) & ~(alignment - 1)); return reinterpret_cast<void*>((reinterpret_cast<size_t>(ptr) + (alignment - 1)) &
~(alignment - 1));
} }
bool IsAligned(uint32_t value, size_t alignment) { bool IsAligned(uint32_t value, size_t alignment) {

View File

@ -211,7 +211,8 @@ typename SerialQueue<T>::StorageIterator SerialQueue<T>::FindUpTo(Serial serial)
// SerialQueue::BeginEnd // SerialQueue::BeginEnd
template <typename T> template <typename T>
SerialQueue<T>::BeginEnd::BeginEnd(typename SerialQueue<T>::StorageIterator start, typename SerialQueue<T>::StorageIterator end) SerialQueue<T>::BeginEnd::BeginEnd(typename SerialQueue<T>::StorageIterator start,
typename SerialQueue<T>::StorageIterator end)
: mStartIt(start), mEndIt(end) { : mStartIt(start), mEndIt(end) {
} }
@ -271,7 +272,8 @@ T& SerialQueue<T>::Iterator::operator*() const {
// SerialQueue::ConstBeginEnd // SerialQueue::ConstBeginEnd
template <typename T> template <typename T>
SerialQueue<T>::ConstBeginEnd::ConstBeginEnd(typename SerialQueue<T>::ConstStorageIterator start, typename SerialQueue<T>::ConstStorageIterator end) SerialQueue<T>::ConstBeginEnd::ConstBeginEnd(typename SerialQueue<T>::ConstStorageIterator start,
typename SerialQueue<T>::ConstStorageIterator end)
: mStartIt(start), mEndIt(end) { : mStartIt(start), mEndIt(end) {
} }
@ -311,12 +313,14 @@ typename SerialQueue<T>::ConstIterator& SerialQueue<T>::ConstIterator::operator+
} }
template <typename T> template <typename T>
bool SerialQueue<T>::ConstIterator::operator==(const typename SerialQueue<T>::ConstIterator& other) const { bool SerialQueue<T>::ConstIterator::operator==(
const typename SerialQueue<T>::ConstIterator& other) const {
return other.mStorageIterator == mStorageIterator && other.mSerialIterator == mSerialIterator; return other.mStorageIterator == mStorageIterator && other.mSerialIterator == mSerialIterator;
} }
template <typename T> template <typename T>
bool SerialQueue<T>::ConstIterator::operator!=(const typename SerialQueue<T>::ConstIterator& other) const { bool SerialQueue<T>::ConstIterator::operator!=(
const typename SerialQueue<T>::ConstIterator& other) const {
return !(*this == other); return !(*this == other);
} }

View File

@ -70,4 +70,4 @@ namespace utils {
} }
} }
} } // namespace utils

View File

@ -47,6 +47,7 @@ namespace utils {
}; };
BackendBinding* CreateBinding(BackendType type); BackendBinding* CreateBinding(BackendType type);
}
} // namespace utils
#endif // UTILS_BACKENDBINDING_H_ #endif // UTILS_BACKENDBINDING_H_

View File

@ -22,27 +22,26 @@
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
#include "GLFW/glfw3native.h" #include "GLFW/glfw3native.h"
#include <initializer_list>
#include <wrl.h>
#include <d3d12.h> #include <d3d12.h>
#include <dxgi1_4.h> #include <dxgi1_4.h>
#include <wrl.h>
#include <initializer_list>
#ifdef _DEBUG #ifdef _DEBUG
#include <dxgidebug.h> #include <dxgidebug.h>
#endif #endif
using Microsoft::WRL::ComPtr; using Microsoft::WRL::ComPtr;
namespace backend { namespace backend { namespace d3d12 {
namespace d3d12 {
void Init(ComPtr<ID3D12Device> d3d12Device, nxtProcTable* procs, nxtDevice* device); void Init(ComPtr<ID3D12Device> d3d12Device, nxtProcTable* procs, nxtDevice* device);
ComPtr<ID3D12CommandQueue> GetCommandQueue(nxtDevice device); ComPtr<ID3D12CommandQueue> GetCommandQueue(nxtDevice device);
uint64_t GetSerial(const nxtDevice device); uint64_t GetSerial(const nxtDevice device);
void NextSerial(nxtDevice device); void NextSerial(nxtDevice device);
void ExecuteCommandLists(nxtDevice device, std::initializer_list<ID3D12CommandList*> commandLists); void ExecuteCommandLists(nxtDevice device,
std::initializer_list<ID3D12CommandList*> commandLists);
void WaitForSerial(nxtDevice device, uint64_t serial); void WaitForSerial(nxtDevice device, uint64_t serial);
void OpenCommandList(nxtDevice device, ComPtr<ID3D12GraphicsCommandList>* commandList); void OpenCommandList(nxtDevice device, ComPtr<ID3D12GraphicsCommandList>* commandList);
} }} // namespace backend::d3d12
}
namespace utils { namespace utils {
namespace { namespace {
@ -56,7 +55,8 @@ namespace utils {
uint32_t dxgiFactoryFlags = 0; uint32_t dxgiFactoryFlags = 0;
#ifdef _DEBUG #ifdef _DEBUG
// Enable the debug layer (requires the Graphics Tools "optional feature"). // Enable the debug layer (requires the Graphics Tools "optional feature").
// NOTE: Enabling the debug layer after device creation will invalidate the active device. // NOTE: Enabling the debug layer after device creation will invalidate the active
// device.
{ {
ComPtr<ID3D12Debug> debugController; ComPtr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
@ -68,7 +68,8 @@ namespace utils {
ComPtr<IDXGIDebug1> dxgiDebug; ComPtr<IDXGIDebug1> dxgiDebug;
if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) { if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) {
dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_ALL)); dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL,
DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_ALL));
} }
} }
#endif #endif
@ -101,7 +102,8 @@ namespace utils {
resourceState |= D3D12_RESOURCE_STATE_COPY_DEST; resourceState |= D3D12_RESOURCE_STATE_COPY_DEST;
} }
if (usage & NXT_TEXTURE_USAGE_BIT_SAMPLED) { if (usage & NXT_TEXTURE_USAGE_BIT_SAMPLED) {
resourceState |= (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); resourceState |= (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
} }
if (usage & NXT_TEXTURE_USAGE_BIT_STORAGE) { if (usage & NXT_TEXTURE_USAGE_BIT_STORAGE) {
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS; resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
@ -112,7 +114,7 @@ namespace utils {
return resourceState; return resourceState;
} }
} } // namespace
class SwapChainImplD3D12 : SwapChainImpl { class SwapChainImplD3D12 : SwapChainImpl {
public: public:
@ -156,8 +158,10 @@ namespace utils {
mCommandQueue = backend::d3d12::GetCommandQueue(mBackendDevice); mCommandQueue = backend::d3d12::GetCommandQueue(mBackendDevice);
} }
nxtSwapChainError Configure(nxtTextureFormat format, nxtTextureUsageBit allowedUsage, nxtSwapChainError Configure(nxtTextureFormat format,
uint32_t width, uint32_t height) { nxtTextureUsageBit allowedUsage,
uint32_t width,
uint32_t height) {
if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) { if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) {
return "unsupported format"; return "unsupported format";
} }
@ -176,21 +180,17 @@ namespace utils {
ComPtr<IDXGISwapChain1> swapChain1; ComPtr<IDXGISwapChain1> swapChain1;
ASSERT_SUCCESS(mFactory->CreateSwapChainForHwnd( ASSERT_SUCCESS(mFactory->CreateSwapChainForHwnd(
mCommandQueue.Get(), mCommandQueue.Get(), mWindow, &swapChainDesc, nullptr, nullptr, &swapChain1));
mWindow,
&swapChainDesc,
nullptr,
nullptr,
&swapChain1
));
ASSERT_SUCCESS(swapChain1.As(&mSwapChain)); ASSERT_SUCCESS(swapChain1.As(&mSwapChain));
for (uint32_t n = 0; n < kFrameCount; ++n) { for (uint32_t n = 0; n < kFrameCount; ++n) {
ASSERT_SUCCESS(mSwapChain->GetBuffer(n, IID_PPV_ARGS(&mRenderTargetResources[n]))); ASSERT_SUCCESS(mSwapChain->GetBuffer(n, IID_PPV_ARGS(&mRenderTargetResources[n])));
} }
// Get the initial render target and arbitrarily choose a "previous" render target that's different // Get the initial render target and arbitrarily choose a "previous" render target
mPreviousRenderTargetIndex = mRenderTargetIndex = mSwapChain->GetCurrentBackBufferIndex(); // that's different
mPreviousRenderTargetIndex = mRenderTargetIndex =
mSwapChain->GetCurrentBackBufferIndex();
mPreviousRenderTargetIndex = mRenderTargetIndex == 0 ? 1 : 0; mPreviousRenderTargetIndex = mRenderTargetIndex == 0 ? 1 : 0;
// Initial the serial for all render targets // Initial the serial for all render targets
@ -220,7 +220,8 @@ namespace utils {
backend::d3d12::OpenCommandList(mBackendDevice, &commandList); backend::d3d12::OpenCommandList(mBackendDevice, &commandList);
D3D12_RESOURCE_BARRIER resourceBarrier; D3D12_RESOURCE_BARRIER resourceBarrier;
resourceBarrier.Transition.pResource = mRenderTargetResources[mPreviousRenderTargetIndex].Get(); resourceBarrier.Transition.pResource =
mRenderTargetResources[mPreviousRenderTargetIndex].Get();
resourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; resourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
resourceBarrier.Transition.StateAfter = mRenderTargetResourceState; resourceBarrier.Transition.StateAfter = mRenderTargetResourceState;
resourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; resourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
@ -237,11 +238,14 @@ namespace utils {
mRenderTargetIndex = mSwapChain->GetCurrentBackBufferIndex(); mRenderTargetIndex = mSwapChain->GetCurrentBackBufferIndex();
// If the next render target is not ready to be rendered yet, wait until it is ready. // If the next render target is not ready to be rendered yet, wait until it is ready.
// If the last completed serial is less than the last requested serial for this render target, // If the last completed serial is less than the last requested serial for this render
// then the commands previously executed on this render target have not yet completed // target, then the commands previously executed on this render target have not yet
backend::d3d12::WaitForSerial(mBackendDevice, mLastSerialRenderTargetWasUsed[mRenderTargetIndex]); // completed
backend::d3d12::WaitForSerial(mBackendDevice,
mLastSerialRenderTargetWasUsed[mRenderTargetIndex]);
mLastSerialRenderTargetWasUsed[mRenderTargetIndex] = backend::d3d12::GetSerial(mBackendDevice); mLastSerialRenderTargetWasUsed[mRenderTargetIndex] =
backend::d3d12::GetSerial(mBackendDevice);
return NXT_SWAP_CHAIN_NO_ERROR; return NXT_SWAP_CHAIN_NO_ERROR;
} }
@ -256,11 +260,8 @@ namespace utils {
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override { void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
mFactory = CreateFactory(); mFactory = CreateFactory();
ASSERT(GetHardwareAdapter(mFactory.Get(), &mHardwareAdapter)); ASSERT(GetHardwareAdapter(mFactory.Get(), &mHardwareAdapter));
ASSERT_SUCCESS(D3D12CreateDevice( ASSERT_SUCCESS(D3D12CreateDevice(mHardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0,
mHardwareAdapter.Get(), IID_PPV_ARGS(&mD3d12Device)));
D3D_FEATURE_LEVEL_11_0,
IID_PPV_ARGS(&mD3d12Device)
));
backend::d3d12::Init(mD3d12Device, procs, device); backend::d3d12::Init(mD3d12Device, procs, device);
mBackendDevice = *device; mBackendDevice = *device;
@ -297,8 +298,10 @@ namespace utils {
break; // No more adapters to enumerate. break; // No more adapters to enumerate.
} }
// Check to see if the adapter supports Direct3D 12, but don't create the actual device yet. // Check to see if the adapter supports Direct3D 12, but don't create the actual
if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) { // device yet.
if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
_uuidof(ID3D12Device), nullptr))) {
*hardwareAdapter = adapter; *hardwareAdapter = adapter;
return true; return true;
} }
@ -312,4 +315,4 @@ namespace utils {
return new D3D12Binding; return new D3D12Binding;
} }
} } // namespace utils

View File

@ -22,16 +22,14 @@
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
#include "GLFW/glfw3native.h" #include "GLFW/glfw3native.h"
#import <QuartzCore/CAMetalLayer.h>
#import <Metal/Metal.h> #import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
namespace backend { namespace backend { namespace metal {
namespace metal {
void Init(id<MTLDevice> metalDevice, nxtProcTable* procs, nxtDevice* device); void Init(id<MTLDevice> metalDevice, nxtProcTable* procs, nxtDevice* device);
void SetNextDrawable(nxtDevice device, id<CAMetalDrawable> drawable); void SetNextDrawable(nxtDevice device, id<CAMetalDrawable> drawable);
void Present(nxtDevice device); void Present(nxtDevice device);
} }}
}
namespace utils { namespace utils {
class SwapChainImplMTL : SwapChainImpl { class SwapChainImplMTL : SwapChainImpl {
@ -51,8 +49,7 @@ namespace utils {
id<CAMetalDrawable> mCurrentDrawable = nil; id<CAMetalDrawable> mCurrentDrawable = nil;
id<MTLTexture> mCurrentTexture = nil; id<MTLTexture> mCurrentTexture = nil;
SwapChainImplMTL(id nsWindow) SwapChainImplMTL(id nsWindow) : mNsWindow(nsWindow) {
: mNsWindow(nsWindow) {
} }
~SwapChainImplMTL() { ~SwapChainImplMTL() {
@ -68,8 +65,10 @@ namespace utils {
mCommandQueue = [mMtlDevice newCommandQueue]; mCommandQueue = [mMtlDevice newCommandQueue];
} }
nxtSwapChainError Configure(nxtTextureFormat format, nxtTextureUsageBit, nxtSwapChainError Configure(nxtTextureFormat format,
uint32_t width, uint32_t height) { nxtTextureUsageBit,
uint32_t width,
uint32_t height) {
if (format != NXT_TEXTURE_FORMAT_B8_G8_R8_A8_UNORM) { if (format != NXT_TEXTURE_FORMAT_B8_G8_R8_A8_UNORM) {
return "unsupported format"; return "unsupported format";
} }
@ -149,5 +148,4 @@ namespace utils {
BackendBinding* CreateMetalBinding() { BackendBinding* CreateMetalBinding() {
return new MetalBinding; return new MetalBinding;
} }
} }

View File

@ -25,7 +25,9 @@
namespace utils { namespace utils {
void FillShaderModuleBuilder(const nxt::ShaderModuleBuilder& builder, nxt::ShaderStage stage, const char* source) { void FillShaderModuleBuilder(const nxt::ShaderModuleBuilder& builder,
nxt::ShaderStage stage,
const char* source) {
shaderc::Compiler compiler; shaderc::Compiler compiler;
shaderc::CompileOptions options; shaderc::CompileOptions options;
@ -60,7 +62,8 @@ namespace utils {
#ifdef DUMP_SPIRV_ASSEMBLY #ifdef DUMP_SPIRV_ASSEMBLY
{ {
auto resultAsm = compiler.CompileGlslToSpvAssembly(source, strlen(source), kind, "myshader?", options); auto resultAsm = compiler.CompileGlslToSpvAssembly(source, strlen(source), kind,
"myshader?", options);
size_t sizeAsm = (resultAsm.cend() - resultAsm.cbegin()); size_t sizeAsm = (resultAsm.cend() - resultAsm.cbegin());
char* buffer = reinterpret_cast<char*>(malloc(sizeAsm + 1)); char* buffer = reinterpret_cast<char*>(malloc(sizeAsm + 1));
@ -86,13 +89,18 @@ namespace utils {
#endif #endif
} }
nxt::ShaderModule CreateShaderModule(const nxt::Device& device, nxt::ShaderStage stage, const char* source) { nxt::ShaderModule CreateShaderModule(const nxt::Device& device,
nxt::ShaderStage stage,
const char* source) {
nxt::ShaderModuleBuilder builder = device.CreateShaderModuleBuilder(); nxt::ShaderModuleBuilder builder = device.CreateShaderModuleBuilder();
FillShaderModuleBuilder(builder, stage, source); FillShaderModuleBuilder(builder, stage, source);
return builder.GetResult(); return builder.GetResult();
} }
nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device, const void* data, uint32_t size, nxt::BufferUsageBit usage) { nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device,
const void* data,
uint32_t size,
nxt::BufferUsageBit usage) {
nxt::Buffer buffer = device.CreateBufferBuilder() nxt::Buffer buffer = device.CreateBufferBuilder()
.SetAllowedUsage(nxt::BufferUsageBit::TransferDst | usage) .SetAllowedUsage(nxt::BufferUsageBit::TransferDst | usage)
.SetInitialUsage(nxt::BufferUsageBit::TransferDst) .SetInitialUsage(nxt::BufferUsageBit::TransferDst)
@ -103,4 +111,4 @@ namespace utils {
return buffer; return buffer;
} }
} } // namespace utils

View File

@ -18,12 +18,23 @@
namespace utils { namespace utils {
void FillShaderModuleBuilder(const nxt::ShaderModuleBuilder& builder, nxt::ShaderStage stage, const char* source); void FillShaderModuleBuilder(const nxt::ShaderModuleBuilder& builder,
nxt::ShaderModule CreateShaderModule(const nxt::Device& device, nxt::ShaderStage stage, const char* source); nxt::ShaderStage stage,
nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device, const void* data, uint32_t size, nxt::BufferUsageBit usage); const char* source);
nxt::ShaderModule CreateShaderModule(const nxt::Device& device,
nxt::ShaderStage stage,
const char* source);
nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device,
const void* data,
uint32_t size,
nxt::BufferUsageBit usage);
template <typename T> template <typename T>
nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device, nxt::BufferUsageBit usage, std::initializer_list<T> data) { nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device,
return CreateFrozenBufferFromData(device, data.begin(), uint32_t(sizeof(T) * data.size()), usage); nxt::BufferUsageBit usage,
} std::initializer_list<T> data) {
return CreateFrozenBufferFromData(device, data.begin(), uint32_t(sizeof(T) * data.size()),
usage);
} }
} // namespace utils

View File

@ -14,11 +14,9 @@
#include "utils/BackendBinding.h" #include "utils/BackendBinding.h"
namespace backend { namespace backend { namespace null {
namespace null {
void Init(nxtProcTable* procs, nxtDevice* device); void Init(nxtProcTable* procs, nxtDevice* device);
} }} // namespace backend::null
}
namespace utils { namespace utils {
@ -37,9 +35,8 @@ namespace utils {
} }
}; };
BackendBinding* CreateNullBinding() { BackendBinding* CreateNullBinding() {
return new NullBinding; return new NullBinding;
} }
} } // namespace utils

View File

@ -19,15 +19,15 @@
#include "nxt/nxt_wsi.h" #include "nxt/nxt_wsi.h"
#include "utils/SwapChainImpl.h" #include "utils/SwapChainImpl.h"
#include <cstdio> // Glad needs to be included before GLFW otherwise it complain that GL.h was already included
#include "glad/glad.h" #include "glad/glad.h"
#include <cstdio>
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
namespace backend { namespace backend { namespace opengl {
namespace opengl {
void Init(void* (*getProc)(const char*), nxtProcTable* procs, nxtDevice* device); void Init(void* (*getProc)(const char*), nxtProcTable* procs, nxtDevice* device);
} }} // namespace backend::opengl
}
namespace utils { namespace utils {
class SwapChainImplGL : SwapChainImpl { class SwapChainImplGL : SwapChainImpl {
@ -45,8 +45,7 @@ namespace utils {
GLuint mBackFBO = 0; GLuint mBackFBO = 0;
GLuint mBackTexture = 0; GLuint mBackTexture = 0;
SwapChainImplGL(GLFWwindow* window) SwapChainImplGL(GLFWwindow* window) : mWindow(window) {
: mWindow(window) {
} }
~SwapChainImplGL() { ~SwapChainImplGL() {
@ -60,17 +59,18 @@ namespace utils {
void Init(nxtWSIContextGL*) { void Init(nxtWSIContextGL*) {
glGenTextures(1, &mBackTexture); glGenTextures(1, &mBackTexture);
glBindTexture(GL_TEXTURE_2D, mBackTexture); glBindTexture(GL_TEXTURE_2D, mBackTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 0, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glGenFramebuffers(1, &mBackFBO); glGenFramebuffers(1, &mBackFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO); glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
GL_TEXTURE_2D, mBackTexture, 0); mBackTexture, 0);
} }
nxtSwapChainError Configure(nxtTextureFormat format, nxtTextureUsageBit, nxtSwapChainError Configure(nxtTextureFormat format,
uint32_t width, uint32_t height) { nxtTextureUsageBit,
uint32_t width,
uint32_t height) {
if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) { if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) {
return "unsupported format"; return "unsupported format";
} }
@ -81,8 +81,8 @@ namespace utils {
glBindTexture(GL_TEXTURE_2D, mBackTexture); glBindTexture(GL_TEXTURE_2D, mBackTexture);
// Reallocate the texture // Reallocate the texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
GL_RGBA, GL_UNSIGNED_BYTE, nullptr); nullptr);
return NXT_SWAP_CHAIN_NO_ERROR; return NXT_SWAP_CHAIN_NO_ERROR;
} }
@ -95,8 +95,8 @@ namespace utils {
nxtSwapChainError Present() { nxtSwapChainError Present() {
glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO); glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT,
GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_NEAREST);
glfwSwapBuffers(mWindow); glfwSwapBuffers(mWindow);
return NXT_SWAP_CHAIN_NO_ERROR; return NXT_SWAP_CHAIN_NO_ERROR;
@ -120,7 +120,8 @@ namespace utils {
} }
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override { void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
glfwMakeContextCurrent(mWindow); glfwMakeContextCurrent(mWindow);
backend::opengl::Init(reinterpret_cast<void*(*)(const char*)>(glfwGetProcAddress), procs, device); backend::opengl::Init(reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress),
procs, device);
mBackendDevice = *device; mBackendDevice = *device;
} }
@ -145,4 +146,4 @@ namespace utils {
return new OpenGLBinding; return new OpenGLBinding;
} }
} } // namespace utils

View File

@ -25,15 +25,14 @@ namespace utils {
auto* ctx = reinterpret_cast<TWSIContext*>(wsiContext); auto* ctx = reinterpret_cast<TWSIContext*>(wsiContext);
reinterpret_cast<TImpl*>(userData)->Init(ctx); reinterpret_cast<TImpl*>(userData)->Init(ctx);
}; };
impl.Destroy = [](void* userData) { impl.Destroy = [](void* userData) { delete reinterpret_cast<TImpl*>(userData); };
delete reinterpret_cast<TImpl*>(userData); impl.Configure = [](void* userData, nxtTextureFormat format,
}; nxtTextureUsageBit allowedUsage, uint32_t width, uint32_t height) {
impl.Configure = [](void* userData, nxtTextureFormat format, nxtTextureUsageBit allowedUsage, uint32_t width, uint32_t height) { return reinterpret_cast<TImpl*>(userData)->Configure(format, allowedUsage, width,
return reinterpret_cast<TImpl*>(userData)->Configure(format, allowedUsage, width, height); height);
}; };
impl.GetNextTexture = [](void* userData, nxtSwapChainNextTexture* nextTexture) { impl.GetNextTexture = [](void* userData, nxtSwapChainNextTexture* nextTexture) {
return reinterpret_cast<TImpl*>(userData)->GetNextTexture( return reinterpret_cast<TImpl*>(userData)->GetNextTexture(nextTexture);
nextTexture);
}; };
impl.Present = [](void* userData) { impl.Present = [](void* userData) {
return reinterpret_cast<TImpl*>(userData)->Present(); return reinterpret_cast<TImpl*>(userData)->Present();
@ -41,6 +40,6 @@ namespace utils {
return impl; return impl;
} }
}; };
} } // namespace utils
#endif // UTILS_SWAPCHAINIMPL_H_ #endif // UTILS_SWAPCHAINIMPL_H_

View File

@ -36,4 +36,4 @@ namespace utils {
# error "Implement USleep for your platform." # error "Implement USleep for your platform."
#endif #endif
} } // namespace utils

View File

@ -15,5 +15,4 @@
namespace utils { namespace utils {
void USleep(unsigned int usecs); void USleep(unsigned int usecs);
} }

View File

@ -17,11 +17,9 @@
#include "nxt/nxt_wsi.h" #include "nxt/nxt_wsi.h"
#include "utils/SwapChainImpl.h" #include "utils/SwapChainImpl.h"
namespace backend { namespace backend { namespace vulkan {
namespace vulkan {
void Init(nxtProcTable* procs, nxtDevice* device); void Init(nxtProcTable* procs, nxtDevice* device);
} }} // namespace backend::vulkan
}
namespace utils { namespace utils {
@ -36,8 +34,7 @@ namespace utils {
private: private:
GLFWwindow* window = nullptr; GLFWwindow* window = nullptr;
SwapChainImplVulkan(GLFWwindow* window) SwapChainImplVulkan(GLFWwindow* window) : window(window) {
: window(window) {
} }
~SwapChainImplVulkan() { ~SwapChainImplVulkan() {
@ -83,9 +80,8 @@ namespace utils {
nxtSwapChainImplementation mSwapchainImpl = {}; nxtSwapChainImplementation mSwapchainImpl = {};
}; };
BackendBinding* CreateVulkanBinding() { BackendBinding* CreateVulkanBinding() {
return new VulkanBinding; return new VulkanBinding;
} }
} } // namespace utils

View File

@ -14,8 +14,7 @@
#include "wire/TerribleCommandBuffer.h" #include "wire/TerribleCommandBuffer.h"
namespace nxt { namespace nxt { namespace wire {
namespace wire {
TerribleCommandBuffer::TerribleCommandBuffer() { TerribleCommandBuffer::TerribleCommandBuffer() {
} }
@ -48,5 +47,4 @@ namespace wire {
mOffset = 0; mOffset = 0;
} }
} }} // namespace nxt::wire
}

View File

@ -19,8 +19,7 @@
#include "wire/Wire.h" #include "wire/Wire.h"
namespace nxt { namespace nxt { namespace wire {
namespace wire {
class TerribleCommandBuffer : public CommandSerializer { class TerribleCommandBuffer : public CommandSerializer {
public: public:
@ -38,7 +37,6 @@ class TerribleCommandBuffer : public CommandSerializer {
uint8_t mBuffer[10000000]; uint8_t mBuffer[10000000];
}; };
} }} // namespace nxt::wire
}
#endif // WIRE_TERRIBLE_COMMAND_BUFFER_H_ #endif // WIRE_TERRIBLE_COMMAND_BUFFER_H_

View File

@ -19,8 +19,7 @@
#include "nxt/nxt.h" #include "nxt/nxt.h"
namespace nxt { namespace nxt { namespace wire {
namespace wire {
class CommandSerializer { class CommandSerializer {
public: public:
@ -35,10 +34,13 @@ namespace wire {
virtual const uint8_t* HandleCommands(const uint8_t* commands, size_t size) = 0; virtual const uint8_t* HandleCommands(const uint8_t* commands, size_t size) = 0;
}; };
CommandHandler* NewClientDevice(nxtProcTable* procs, nxtDevice* device, CommandSerializer* serializer); CommandHandler* NewClientDevice(nxtProcTable* procs,
CommandHandler* NewServerCommandHandler(nxtDevice device, const nxtProcTable& procs, CommandSerializer* serializer); nxtDevice* device,
CommandSerializer* serializer);
CommandHandler* NewServerCommandHandler(nxtDevice device,
const nxtProcTable& procs,
CommandSerializer* serializer);
} }} // namespace nxt::wire
}
#endif // WIRE_WIRE_H_ #endif // WIRE_WIRE_H_

View File

@ -14,8 +14,7 @@
#include "wire/WireCmd.h" #include "wire/WireCmd.h"
namespace nxt { namespace nxt { namespace wire {
namespace wire {
size_t ReturnDeviceErrorCallbackCmd::GetRequiredSize() const { size_t ReturnDeviceErrorCallbackCmd::GetRequiredSize() const {
return sizeof(*this) + messageStrlen + 1; return sizeof(*this) + messageStrlen + 1;
@ -45,5 +44,4 @@ namespace wire {
return this + 1; return this + 1;
} }
} }} // namespace nxt::wire
}

View File

@ -17,8 +17,7 @@
#include "wire/WireCmd_autogen.h" #include "wire/WireCmd_autogen.h"
namespace nxt { namespace nxt { namespace wire {
namespace wire {
struct ReturnDeviceErrorCallbackCmd { struct ReturnDeviceErrorCallbackCmd {
wire::ReturnWireCmd commandId = ReturnWireCmd::DeviceErrorCallback; wire::ReturnWireCmd commandId = ReturnWireCmd::DeviceErrorCallback;
@ -55,7 +54,6 @@ namespace wire {
const void* GetData() const; const void* GetData() const;
}; };
} }} // namespace nxt::wire
}
#endif // WIRE_WIRECMD_H_ #endif // WIRE_WIRECMD_H_