diff --git a/Audio/DynamicSoundEffectInstance.cpp b/Audio/DynamicSoundEffectInstance.cpp index 29437e9a..ce2295e2 100644 --- a/Audio/DynamicSoundEffectInstance.cpp +++ b/Audio/DynamicSoundEffectInstance.cpp @@ -31,6 +31,9 @@ class DynamicSoundEffectInstance::Impl : public IVoiceNotify mBufferNeeded(nullptr), mObject(object) { + if (!engine) + throw std::invalid_argument("AudioEngine is required"); + if ((sampleRate < XAUDIO2_MIN_SAMPLE_RATE) || (sampleRate > XAUDIO2_MAX_SAMPLE_RATE)) { @@ -55,6 +58,12 @@ class DynamicSoundEffectInstance::Impl : public IVoiceNotify throw std::invalid_argument("DynamicSoundEffectInstance supports 8 or 16 bit"); } + if (!bufferNeeded) + { + DebugTrace("DynamicSoundEffectInstance requires a valid callback\n"); + throw std::invalid_argument("DynamicSoundEffectInstance"); + } + mBufferEvent.reset(CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); if (!mBufferEvent) { @@ -63,7 +72,6 @@ class DynamicSoundEffectInstance::Impl : public IVoiceNotify CreateIntegerPCM(&mWaveFormat, sampleRate, channels, sampleBits); - assert(engine != nullptr); engine->RegisterNotify(this, true); mBase.Initialize(engine, &mWaveFormat, flags); diff --git a/Audio/SoundCommon.cpp b/Audio/SoundCommon.cpp index cd5a6258..cf6bf071 100644 --- a/Audio/SoundCommon.cpp +++ b/Audio/SoundCommon.cpp @@ -521,6 +521,9 @@ void DirectX::CreateIntegerPCM( int channels, int sampleBits) noexcept { + if (!wfx) + return; + const int blockAlign = channels * sampleBits / 8; wfx->wFormatTag = WAVE_FORMAT_PCM; @@ -541,6 +544,9 @@ void DirectX::CreateFloatPCM( int sampleRate, int channels) noexcept { + if (!wfx) + return; + const int blockAlign = channels * 4; wfx->wFormatTag = WAVE_FORMAT_IEEE_FLOAT; @@ -563,6 +569,9 @@ void DirectX::CreateADPCM( int channels, int samplesPerBlock) noexcept(false) { + if (!wfx) + return; + if (wfxSize < (sizeof(WAVEFORMATEX) + MSADPCM_FORMAT_EXTRA_BYTES)) { DebugTrace("CreateADPCM needs at least %zu bytes for the result\n", @@ -608,6 +617,9 @@ void DirectX::CreateXWMA( int avgBytes, bool wma3) noexcept { + if (!wfx) + return; + wfx->wFormatTag = static_cast((wma3) ? WAVE_FORMAT_WMAUDIO3 : WAVE_FORMAT_WMAUDIO2); wfx->nChannels = static_cast(channels); wfx->nSamplesPerSec = static_cast(sampleRate); diff --git a/Audio/SoundCommon.h b/Audio/SoundCommon.h index cdb6c855..b2cd20ca 100644 --- a/Audio/SoundCommon.h +++ b/Audio/SoundCommon.h @@ -13,6 +13,8 @@ #include "Audio.h" #include "PlatformHelpers.h" +#include + #ifdef USING_XAUDIO2_9 #define DIRECTX_ENABLE_XWMA #endif diff --git a/Audio/SoundEffect.cpp b/Audio/SoundEffect.cpp index fb5bdbea..687973e0 100644 --- a/Audio/SoundEffect.cpp +++ b/Audio/SoundEffect.cpp @@ -50,7 +50,9 @@ class SoundEffect::Impl : public IVoiceNotify , mXMAMemory(nullptr) #endif { - assert(mEngine != nullptr); + if (!engine) + throw std::invalid_argument("AudioEngine is required"); + mEngine->RegisterNotify(this, false); } diff --git a/Audio/WaveBank.cpp b/Audio/WaveBank.cpp index 0991bd03..dfb8f8da 100644 --- a/Audio/WaveBank.cpp +++ b/Audio/WaveBank.cpp @@ -33,7 +33,9 @@ class WaveBank::Impl : public IVoiceNotify mPrepared(false), mStreaming(false) { - assert(mEngine != nullptr); + if (!engine) + throw std::invalid_argument("AudioEngine is required"); + mEngine->RegisterNotify(this, false); } diff --git a/Audio/WaveBankReader.cpp b/Audio/WaveBankReader.cpp index eea53ad7..ed1fc34f 100644 --- a/Audio/WaveBankReader.cpp +++ b/Audio/WaveBankReader.cpp @@ -517,6 +517,9 @@ HRESULT WaveBankReader::Impl::Open(const wchar_t* szFileName) noexcept(false) Close(); Clear(); + if (!szFileName) + return E_INVALIDARG; + m_prepared = false; m_event.reset(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_MODIFY_STATE | SYNCHRONIZE)); @@ -1029,7 +1032,7 @@ HRESULT WaveBankReader::Impl::GetWaveData(uint32_t index, const uint8_t** pData, #endif if (!waveData) - return E_FAIL; + return E_POINTER; if (m_data.dwFlags & BANKDATA::TYPE_STREAMING) { @@ -1223,10 +1226,13 @@ HRESULT WaveBankReader::Open(const wchar_t* szFileName) noexcept _Use_decl_annotations_ uint32_t WaveBankReader::Find(const char* name) const { - auto it = pImpl->m_names.find(name); - if (it != pImpl->m_names.cend()) + if (name) { - return it->second; + auto it = pImpl->m_names.find(name); + if (it != pImpl->m_names.cend()) + { + return it->second; + } } return uint32_t(-1); diff --git a/Inc/DirectXHelpers.h b/Inc/DirectXHelpers.h index adbf8588..f9b71cb7 100644 --- a/Inc/DirectXHelpers.h +++ b/Inc/DirectXHelpers.h @@ -201,6 +201,9 @@ namespace DirectX _In_ const D3D12_ROOT_SIGNATURE_DESC* rootSignatureDesc, _Out_ ID3D12RootSignature** rootSignature) noexcept { + if (!device || !rootSignatureDesc || !rootSignature) + return E_INVALIDARG; + Microsoft::WRL::ComPtr pSignature; Microsoft::WRL::ComPtr pError; HRESULT hr = D3D12SerializeRootSignature(rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, pSignature.GetAddressOf(), pError.GetAddressOf()); @@ -217,6 +220,9 @@ namespace DirectX DIRECTX_TOOLKIT_API inline XMUINT2 GetTextureSize(_In_ ID3D12Resource* tex) noexcept { + if (!tex) + return XMUINT2(0, 0); + #if defined(_MSC_VER) || !defined(_WIN32) const auto desc = tex->GetDesc(); #else diff --git a/README.md b/README.md index 4fdd8d0d..b33bbab7 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ For a full change history, see [CHANGELOG.md](https://github.com/microsoft/Direc ## Support -For questions, consider using [Stack Overflow](https://stackoverflow.com/questions/tagged/directxtk) with the _directxtk_ tag, or the [DirectX Discord Server](https://discord.gg/directx) in the _dx12-developers_ channel. +For questions, consider using [Stack Overflow](https://stackoverflow.com/questions/tagged/directxtk) with the _directxtk_ tag, or the [DirectX Discord Server](https://discord.gg/directx) in the _dx12-developers_ or _input-and-audio_ channels. For bug reports and feature requests, please use GitHub [issues](https://github.com/microsoft/DirectXTK12/issues) for this project. diff --git a/Src/BinaryReader.h b/Src/BinaryReader.h index 0d4d96c4..e6cbe290 100644 --- a/Src/BinaryReader.h +++ b/Src/BinaryReader.h @@ -27,6 +27,9 @@ namespace DirectX explicit BinaryReader(_In_z_ wchar_t const* fileName) noexcept(false); BinaryReader(_In_reads_bytes_(dataSize) uint8_t const* dataBlob, size_t dataSize) noexcept; + BinaryReader(BinaryReader&&) noexcept; + BinaryReader& operator= (BinaryReader&&) noexcept; + BinaryReader(BinaryReader const&) = delete; BinaryReader& operator= (BinaryReader const&) = delete; diff --git a/Src/CommonStates.cpp b/Src/CommonStates.cpp index a5d262a4..ad520b92 100644 --- a/Src/CommonStates.cpp +++ b/Src/CommonStates.cpp @@ -456,6 +456,9 @@ class CommonStates::Impl explicit Impl(_In_ ID3D12Device* device) : mDescriptors(device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, static_cast(SamplerIndex::Count)) { + if (!device) + throw std::invalid_argument("Direct3D device is null"); + SetDebugObjectName(mDescriptors.Heap(), L"CommonStates"); for (size_t i = 0; i < static_cast(SamplerIndex::Count); ++i) diff --git a/Src/DirectXHelpers.cpp b/Src/DirectXHelpers.cpp index b958d9e9..a5609530 100644 --- a/Src/DirectXHelpers.cpp +++ b/Src/DirectXHelpers.cpp @@ -21,6 +21,9 @@ void DirectX::CreateShaderResourceView( D3D12_CPU_DESCRIPTOR_HANDLE srvDescriptor, bool isCubeMap) { + if (!device || !tex) + throw std::invalid_argument("Direct3D device and resource must be valid"); + #if defined(_MSC_VER) || !defined(_WIN32) const auto desc = tex->GetDesc(); #else @@ -109,6 +112,9 @@ void DirectX::CreateUnorderedAccessView( D3D12_CPU_DESCRIPTOR_HANDLE uavDescriptor, uint32_t mipLevel) { + if (!device || !tex) + throw std::invalid_argument("Direct3D device and resource must be valid"); + #if defined(_MSC_VER) || !defined(_WIN32) const auto desc = tex->GetDesc(); #else @@ -182,6 +188,9 @@ void DirectX::CreateRenderTargetView( D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor, uint32_t mipLevel) { + if (!device || !tex) + throw std::invalid_argument("Direct3D device and resource must be valid"); + #if defined(_MSC_VER) || !defined(_WIN32) const auto desc = tex->GetDesc(); #else @@ -267,6 +276,9 @@ void DirectX::CreateBufferShaderResourceView( D3D12_CPU_DESCRIPTOR_HANDLE srvDescriptor, uint32_t stride) { + if (!device || !buffer) + throw std::invalid_argument("Direct3D device and resource must be valid"); + #if defined(_MSC_VER) || !defined(_WIN32) const auto desc = buffer->GetDesc(); #else @@ -304,6 +316,9 @@ void DirectX::CreateBufferUnorderedAccessView( uint32_t counterOffset, ID3D12Resource* counterResource) { + if (!device || !buffer) + throw std::invalid_argument("Direct3D device and resource must be valid"); + #if defined(_MSC_VER) || !defined(_WIN32) const auto desc = buffer->GetDesc(); #else diff --git a/Src/PBREffectFactory.cpp b/Src/PBREffectFactory.cpp index 74f459bd..4aa6e31a 100644 --- a/Src/PBREffectFactory.cpp +++ b/Src/PBREffectFactory.cpp @@ -88,6 +88,9 @@ class PBREffectFactory::Impl , mSamplerDescriptors(nullptr) , mDevice(device) { + if (!device) + throw std::invalid_argument("Direct3D device is null"); + if (textureDescriptors) mTextureDescriptors = std::make_unique(textureDescriptors); if (samplerDescriptors) diff --git a/Src/ResourceUploadBatch.cpp b/Src/ResourceUploadBatch.cpp index 320ee6d1..27e11775 100644 --- a/Src/ResourceUploadBatch.cpp +++ b/Src/ResourceUploadBatch.cpp @@ -302,14 +302,16 @@ class ResourceUploadBatch::Impl { public: Impl( - _In_ ID3D12Device* device) noexcept + _In_ ID3D12Device* device) : mDevice(device) , mCommandType(D3D12_COMMAND_LIST_TYPE_DIRECT) , mInBeginEndBlock(false) , mTypedUAVLoadAdditionalFormats(false) , mStandardSwizzle64KBSupported(false) { - assert(device != nullptr); + if (!device) + throw std::invalid_argument("Direct3D device is null"); + D3D12_FEATURE_DATA_D3D12_OPTIONS options = {}; if (SUCCEEDED(device->CheckFeatureSupport( D3D12_FEATURE_D3D12_OPTIONS, @@ -358,7 +360,7 @@ class ResourceUploadBatch::Impl } // Asynchronously uploads a resource. The memory in subRes is copied. - // The resource must be in the COPY_DEST state. + // The resource must be in the COPY_DEST or COMMON state. void Upload( _In_ ID3D12Resource* resource, uint32_t subresourceIndexStart, @@ -368,6 +370,9 @@ class ResourceUploadBatch::Impl if (!mInBeginEndBlock) throw std::logic_error("Can't call Upload on a closed ResourceUploadBatch."); + if (!resource || !subRes || !numSubresources) + throw std::invalid_argument("Resource/subresource are null"); + const UINT64 uploadSize = GetRequiredIntermediateSize( resource, subresourceIndexStart, @@ -409,6 +414,9 @@ class ResourceUploadBatch::Impl if (!mInBeginEndBlock) throw std::logic_error("Can't call Upload on a closed ResourceUploadBatch."); + if (!resource) + throw std::invalid_argument("Resource is null"); + // Submit resource copy to command list mList->CopyBufferRegion(resource, 0, buffer.Resource(), buffer.ResourceOffset(), buffer.Size()); @@ -420,14 +428,12 @@ class ResourceUploadBatch::Impl // Resource must be in the PIXEL_SHADER_RESOURCE state void GenerateMips(_In_ ID3D12Resource* resource) { - if (resource == nullptr) - { - throw std::invalid_argument("Nullptr passed to GenerateMips"); - } - if (!mInBeginEndBlock) throw std::logic_error("Can't call GenerateMips on a closed ResourceUploadBatch."); + if (!resource) + throw std::invalid_argument("GenerateMips resource is null"); + if (mCommandType == D3D12_COMMAND_LIST_TYPE_COPY) { DebugTrace("ERROR: GenerateMips cannot operate on a copy queue\n"); @@ -508,6 +514,9 @@ class ResourceUploadBatch::Impl if (!mInBeginEndBlock) throw std::logic_error("Can't call Upload on a closed ResourceUploadBatch."); + if (!resource) + throw std::invalid_argument("Transition resource is null"); + if (mCommandType == D3D12_COMMAND_LIST_TYPE_COPY) { switch (stateAfter) @@ -551,6 +560,9 @@ class ResourceUploadBatch::Impl if (!mInBeginEndBlock) throw std::logic_error("ResourceUploadBatch already closed."); + if (!commandQueue) + throw std::invalid_argument("Direct3D queue is null"); + ThrowIfFailed(mList->Close()); // Submit the job to the GPU diff --git a/Src/SpriteBatch.cpp b/Src/SpriteBatch.cpp index b2aab7af..157d1f37 100644 --- a/Src/SpriteBatch.cpp +++ b/Src/SpriteBatch.cpp @@ -444,7 +444,7 @@ SpriteBatch::Impl::Impl(ID3D12Device* device, mVertexSegment{}, mVertexPageSize(sizeof(VertexPositionColorTexture) * MaxBatchSize * VerticesPerSprite), mSpriteCount(0), - mDeviceResources(deviceResourcesPool.DemandCreate(device, upload)) + mDeviceResources{} { if (!device) throw std::invalid_argument("Direct3D device is null"); @@ -455,6 +455,8 @@ SpriteBatch::Impl::Impl(ID3D12Device* device, mSetViewport = true; } + mDeviceResources = deviceResourcesPool.DemandCreate(device, upload); + D3D12_GRAPHICS_PIPELINE_STATE_DESC d3dDesc = {}; d3dDesc.InputLayout = s_DefaultInputLayoutDesc; d3dDesc.BlendState = psoDesc.blendDesc; diff --git a/Src/SpriteFont.cpp b/Src/SpriteFont.cpp index 0c0370ca..dca07fcd 100644 --- a/Src/SpriteFont.cpp +++ b/Src/SpriteFont.cpp @@ -203,6 +203,11 @@ SpriteFont::Impl::Impl( lineSpacing(ilineSpacing), utfBufferSize(0) { + if (!itexture.ptr) + { + throw std::invalid_argument("Sprite sheet texture required"); + } + if (!std::is_sorted(iglyphs, iglyphs + glyphCount)) { throw std::runtime_error("Glyphs must be in ascending codepoint order"); diff --git a/Src/ToneMapPostProcess.cpp b/Src/ToneMapPostProcess.cpp index 2bfbd9bb..3259033b 100644 --- a/Src/ToneMapPostProcess.cpp +++ b/Src/ToneMapPostProcess.cpp @@ -317,7 +317,7 @@ ToneMapPostProcess::Impl::Impl(_In_ ID3D12Device* device, const RenderTargetStat if (op >= Operator_Max) throw std::invalid_argument("Tonemap operator not defined"); - if (func > TransferFunction_Max) + if (func >= TransferFunction_Max) throw std::invalid_argument("Transfer function not defined"); if (!device)