diff --git a/lib/audiodev/AudioMatrix.cpp b/lib/audiodev/AudioMatrix.cpp index a01b730..e021406 100644 --- a/lib/audiodev/AudioMatrix.cpp +++ b/lib/audiodev/AudioMatrix.cpp @@ -28,7 +28,7 @@ void AudioMatrixMono::bufferMonoSampleData(IAudioVoice& voice, const int16_t* da m_interleaveBuf.clear(); m_interleaveBuf.reserve(samples * chmap.m_channelCount); for (size_t s=0 ; sneedsNextBuffer(&m_voice, m_voice.m_bufferFrames); + m_voice.m_cb->needsNextBuffer(m_voice, m_voice.m_bufferFrames); } STDMETHOD_(void, OnBufferStart)(void* pBufferContext) {} STDMETHOD_(void, OnLoopEnd)(void* pBufferContext) {} @@ -48,11 +48,12 @@ struct XA2AudioVoice : IAudioVoice desc.nSamplesPerSec = sampleRate; desc.wBitsPerSample = 16; desc.nBlockAlign = desc.nChannels * desc.wBitsPerSample / 8; - desc.nAvgBytesPerSec = desc.nAvgBytesPerSec * desc.nBlockAlign; + desc.nAvgBytesPerSec = desc.nSamplesPerSec * desc.nBlockAlign; - if FAILED(xa2.CreateSourceVoice(&m_voiceQueue, &desc, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &m_xaCb)) + HRESULT err = xa2.CreateSourceVoice(&m_voiceQueue, &desc, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &m_xaCb); + if (FAILED(err)) { - Log.report(logvisor::Error, "unable to create source voice"); + Log.report(logvisor::Fatal, "unable to create source voice"); return; } @@ -114,7 +115,7 @@ struct XA2AudioVoice : IAudioVoice m_frameSize = chCount * 2; for (unsigned i=0 ; i<3 ; ++i) - m_cb->needsNextBuffer(this, m_bufferFrames); + m_cb->needsNextBuffer(*this, m_bufferFrames); } void bufferSampleData(const int16_t* data, size_t frames) @@ -122,8 +123,15 @@ struct XA2AudioVoice : IAudioVoice XAUDIO2_BUFFER* buf = &m_buffers[m_fillBuf++]; if (m_fillBuf == 3) m_fillBuf = 0; + buf->Flags = 0; buf->AudioBytes = frames * m_frameSize; buf->pAudioData = reinterpret_cast(data); + buf->PlayBegin = 0; + buf->PlayLength = 0; + buf->LoopBegin = 0; + buf->LoopLength = 0; + buf->LoopCount = 0; + buf->pContext = nullptr; m_voiceQueue->SubmitSourceBuffer(buf); } @@ -143,28 +151,43 @@ struct XA2AudioVoice : IAudioVoice } }; +typedef HRESULT (__stdcall *PFN_XAudio2Create)(_Outptr_ IXAudio2** ppXAudio2, UINT32 Flags, + XAUDIO2_PROCESSOR XAudio2Processor); + +static PFN_XAudio2Create MyXAudio2Create = nullptr; + struct XA2AudioVoiceAllocator : IAudioVoiceAllocator { ComPtr m_xa2; IXAudio2MasteringVoice* m_masterVoice; - AudioChannelSet m_maxSet; + AudioChannelSet m_maxSet = AudioChannelSet::Unknown; XA2AudioVoiceAllocator() { - if (FAILED(XAudio2Create(&m_xa2))) + if (!MyXAudio2Create) { - Log.report(logvisor::Error, "Unable to initialize XAudio2"); + HMODULE mod = LoadLibraryW(XAUDIO2_DLL_W); + if (!mod) + Log.report(logvisor::Fatal, L"unable to load " XAUDIO2_DLL_W); + MyXAudio2Create = PFN_XAudio2Create(GetProcAddress(mod, "XAudio2Create")); + if (!MyXAudio2Create) + Log.report(logvisor::Fatal, L"unable to find XAudio2Create in " XAUDIO2_DLL_W); + } + + if (FAILED(MyXAudio2Create(&m_xa2, 0, XAUDIO2_DEFAULT_PROCESSOR))) + { + Log.report(logvisor::Fatal, "Unable to initialize XAudio2"); return; } if (FAILED(m_xa2->CreateMasteringVoice(&m_masterVoice))) { - Log.report(logvisor::Error, "Unable to initialize XAudio2 mastering voice"); + Log.report(logvisor::Fatal, "Unable to initialize XAudio2 mastering voice"); return; } DWORD channelMask; if (FAILED(m_masterVoice->GetChannelMask(&channelMask))) { - Log.report(logvisor::Error, "Unable to get mastering voice's channel mask"); + Log.report(logvisor::Fatal, "Unable to get mastering voice's channel mask"); return; } if ((channelMask & (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)) == (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)) @@ -190,17 +213,24 @@ struct XA2AudioVoiceAllocator : IAudioVoiceAllocator m_masterVoice->DestroyVoice(); } + AudioChannelSet getAvailableSet() + { + return m_maxSet; + } + std::unique_ptr allocateNewVoice(AudioChannelSet layoutOut, unsigned sampleRate, IAudioVoiceCallback* cb) { AudioChannelSet acset = std::min(layoutOut, m_maxSet); - XA2AudioVoice* newVoice = new XA2AudioVoice(*m_xa2.Get(), acset, sampleRate, cb); - std::unique_ptr ret(newVoice); - if (!newVoice->m_voiceQueue) + std::unique_ptr newVoice = std::make_unique + (*m_xa2.Get(), acset, sampleRate, cb); + if (!static_cast(newVoice.get())->m_voiceQueue) return {}; - return ret; + return newVoice; } + + void pumpVoices() {} }; std::unique_ptr NewAudioVoiceAllocator() diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index 2cb0efe..e7be956 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -264,7 +264,7 @@ class D3D11TextureD : public ITextureD m_cpuBuf.reset(new uint8_t[m_cpuSz]); CD3D11_TEXTURE2D_DESC desc(pixelFmt, width, height, 1, 1, - D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, D3D11_CPU_ACCESS_WRITE); + D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); for (int i=0 ; i<3 ; ++i) { ThrowIfFailed(ctx->m_dev->CreateTexture2D(&desc, nullptr, &m_texs[i])); diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index f03e366..3e8d8ff 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -338,24 +338,32 @@ class D3D12TextureD : public ITextureD D3D12CommandQueue* m_q; D3D12_RESOURCE_DESC m_gpuDesc; std::unique_ptr m_cpuBuf; + size_t m_rowPitch; size_t m_cpuSz; int m_validSlots = 0; D3D12TextureD(D3D12CommandQueue* q, D3D12Context* ctx, size_t width, size_t height, TextureFormat fmt) - : m_fmt(fmt), m_q(q) + : m_width(width), m_height(height), m_fmt(fmt), m_q(q) { DXGI_FORMAT pixelFmt; + size_t pxPitch; switch (fmt) { case TextureFormat::RGBA8: pixelFmt = DXGI_FORMAT_R8G8B8A8_UNORM; + pxPitch = 4; break; case TextureFormat::I8: pixelFmt = DXGI_FORMAT_R8_UNORM; + pxPitch = 1; break; default: Log.report(logvisor::Fatal, "unsupported tex format"); } + m_cpuSz = width * height * pxPitch; + m_rowPitch = width * pxPitch; + m_cpuBuf.reset(new uint8_t[m_cpuSz]); + m_gpuDesc = CD3DX12_RESOURCE_DESC::Tex2D(pixelFmt, width, height); size_t reqSz = GetRequiredIntermediateSize(ctx->m_dev.Get(), &m_gpuDesc, 0, 1); for (int i=0 ; i<2 ; ++i) @@ -1389,13 +1397,21 @@ void D3D12TextureD::update(int b) m_q->stallDynamicUpload(); ID3D12Resource* res = m_texs[b].Get(); ID3D12Resource* gpuRes = m_gpuTexs[b].Get(); - D3D12_SUBRESOURCE_DATA d = {m_cpuBuf.get(), LONG_PTR(m_width * 4), LONG_PTR(m_cpuSz)}; - m_q->m_dynamicCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, - D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_DEST)); + D3D12_SUBRESOURCE_DATA d = {m_cpuBuf.get(), LONG_PTR(m_rowPitch), LONG_PTR(m_cpuSz)}; + D3D12_RESOURCE_BARRIER setupCopy[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_DEST), + }; + m_q->m_dynamicCmdList->ResourceBarrier(1, setupCopy); if (!UpdateSubresources<1>(m_q->m_dynamicCmdList.Get(), gpuRes, res, 0, 0, 1, &d)) Log.report(logvisor::Fatal, "unable to update dynamic texture data"); - m_q->m_dynamicCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, - D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); + D3D12_RESOURCE_BARRIER teardownCopy[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, + D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE), + }; + m_q->m_dynamicCmdList->ResourceBarrier(1, teardownCopy); m_validSlots |= slot; } } diff --git a/lib/win/ApplicationWin32.cpp b/lib/win/ApplicationWin32.cpp index 7539da7..82a4e6a 100644 --- a/lib/win/ApplicationWin32.cpp +++ b/lib/win/ApplicationWin32.cpp @@ -285,6 +285,7 @@ public: int clientReturn = 0; std::thread clientThread([&]() { + CoInitializeEx(nullptr, COINIT_MULTITHREADED); clientReturn = m_callback.appMain(this); PostThreadMessage(g_mainThreadId, WM_USER+1, 0, 0); });