Fix D3D12 runtime errors

This commit is contained in:
2025-09-23 02:56:01 +09:00
parent 5cff7466fb
commit 7fa3ab2442
2 changed files with 31 additions and 73 deletions

View File

@@ -75,7 +75,6 @@ HRESULT SimpleGPURenderer::Initialize(winrt::Microsoft::UI::Xaml::Controls::Swap
if (FAILED(hr)) return hr;
m_initialized = true;
std::cout << "[SimpleGPURenderer] Initialized successfully (" << width << "x" << height << ")" << std::endl;
return S_OK;
}
@@ -120,7 +119,6 @@ void SimpleGPURenderer::Shutdown()
m_device.Reset();
m_initialized = false;
std::cout << "[SimpleGPURenderer] Shutdown completed" << std::endl;
}
HRESULT SimpleGPURenderer::RenderVideoFrame(const VideoFrame& frame)
@@ -135,8 +133,6 @@ HRESULT SimpleGPURenderer::RenderVideoFrame(const VideoFrame& frame)
HRESULT hr = S_OK;
// 1. TRIPLE BUFFERING DEBUG: Check frame completion status
std::cout << "[SimpleGPURenderer] Frame " << m_frameIndex << " - Current fence: " << m_fence->GetCompletedValue()
<< ", Target: " << m_frameCompletionValues[m_frameIndex] << std::endl;
WaitForFrameCompletion(m_frameIndex);
@@ -160,7 +156,9 @@ HRESULT SimpleGPURenderer::RenderVideoFrame(const VideoFrame& frame)
// 5. Advance to next frame (triple buffering rotation)
m_frameIndex = (m_frameIndex + 1) % FrameCount;
std::cout << "[SimpleGPURenderer] Frame rendered successfully (" << frame.width << "x" << frame.height << "), frame index: " << m_frameIndex << std::endl;
// 6. Increment total frame counter
m_totalFramesRendered++;
return S_OK;
}
@@ -176,8 +174,7 @@ bool SimpleGPURenderer::TryRenderFrame(const VideoFrame& frame)
return false;
}
catch (...) {
std::cout << "[SimpleGPURenderer] Exception caught in TryRenderFrame - falling back to CPU" << std::endl;
return false;
return false;
}
}
@@ -218,7 +215,6 @@ HRESULT SimpleGPURenderer::CreateDevice()
return hr;
}
std::cout << "[SimpleGPURenderer] D3D12 device created successfully" << std::endl;
return S_OK;
}
@@ -306,7 +302,6 @@ HRESULT SimpleGPURenderer::CreateDescriptorHeaps()
m_srvUavDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
std::cout << "[SimpleGPURenderer] Descriptor heaps created successfully" << std::endl;
return S_OK;
}
@@ -328,7 +323,6 @@ HRESULT SimpleGPURenderer::CreateRenderTargets()
rtvHandle.ptr += m_rtvDescriptorSize;
}
std::cout << "[SimpleGPURenderer] Render targets created successfully" << std::endl;
return S_OK;
}
@@ -373,7 +367,6 @@ HRESULT SimpleGPURenderer::CreateSynchronizationObjects()
return hr;
}
std::cout << "[SimpleGPURenderer] Synchronization objects created successfully" << std::endl;
return S_OK;
}
@@ -418,7 +411,6 @@ HRESULT SimpleGPURenderer::CreateComputeShaderResources()
return hr;
}
std::cout << "[SimpleGPURenderer] Compute shader resources created successfully" << std::endl;
return S_OK;
}
@@ -451,7 +443,7 @@ HRESULT SimpleGPURenderer::CreateVideoTextures(uint32_t videoWidth, uint32_t vid
textureDesc.Width = videoWidth;
textureDesc.Height = videoHeight;
hr = m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &textureDesc,
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, nullptr, IID_PPV_ARGS(&m_yTextures[i]));
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, IID_PPV_ARGS(&m_yTextures[i]));
if (FAILED(hr))
{
std::cout << "[SimpleGPURenderer] Failed to create Y texture " << i << ": 0x" << std::hex << hr << std::endl;
@@ -462,7 +454,7 @@ HRESULT SimpleGPURenderer::CreateVideoTextures(uint32_t videoWidth, uint32_t vid
textureDesc.Width = videoWidth / 2;
textureDesc.Height = videoHeight / 2;
hr = m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &textureDesc,
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, nullptr, IID_PPV_ARGS(&m_uTextures[i]));
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, IID_PPV_ARGS(&m_uTextures[i]));
if (FAILED(hr))
{
std::cout << "[SimpleGPURenderer] Failed to create U texture " << i << ": 0x" << std::hex << hr << std::endl;
@@ -471,7 +463,7 @@ HRESULT SimpleGPURenderer::CreateVideoTextures(uint32_t videoWidth, uint32_t vid
// V texture (half resolution for 4:2:0)
hr = m_device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &textureDesc,
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, nullptr, IID_PPV_ARGS(&m_vTextures[i]));
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, IID_PPV_ARGS(&m_vTextures[i]));
if (FAILED(hr))
{
std::cout << "[SimpleGPURenderer] Failed to create V texture " << i << ": 0x" << std::hex << hr << std::endl;
@@ -572,14 +564,12 @@ HRESULT SimpleGPURenderer::CreateVideoTextures(uint32_t videoWidth, uint32_t vid
m_device->CreateUnorderedAccessView(m_rgbTextures[frameIdx].Get(), nullptr, &uavDesc, frameHandle);
}
std::cout << "[SimpleGPURenderer] Descriptor views created for " << FrameCount << " frame sets (triple buffering)" << std::endl;
}
else
{
std::cout << "[SimpleGPURenderer] Warning: SRV/UAV heap not available for descriptor creation" << std::endl;
}
std::cout << "[SimpleGPURenderer] Video textures created (" << videoWidth << "x" << videoHeight << ")" << std::endl;
return S_OK;
}
@@ -603,7 +593,6 @@ HRESULT SimpleGPURenderer::ExecuteGPUPipeline(const VideoFrame& frame)
return hr;
}
std::cout << "[SimpleGPURenderer] Starting GPU pipeline for frame " << m_frameIndex << std::endl;
// Step 2: Update video textures (upload YUV data)
hr = UpdateVideoTexturesInternal(frame);
@@ -627,7 +616,6 @@ HRESULT SimpleGPURenderer::ExecuteGPUPipeline(const VideoFrame& frame)
ID3D12CommandList* commandLists[] = { m_commandList.Get() };
m_commandQueue->ExecuteCommandLists(1, commandLists);
std::cout << "[SimpleGPURenderer] GPU pipeline executed successfully" << std::endl;
return S_OK;
}
@@ -646,7 +634,6 @@ HRESULT SimpleGPURenderer::UpdateVideoTexturesInternal(const VideoFrame& frame)
if (!m_yUploadBuffers[m_frameIndex] || !m_uUploadBuffers[m_frameIndex] || !m_vUploadBuffers[m_frameIndex])
return E_FAIL;
std::cout << "[SimpleGPURenderer] Using upload buffers for frame " << m_frameIndex << std::endl;
HRESULT hr = S_OK;
if (!m_commandAllocators[m_frameIndex] || !m_commandList)
@@ -655,7 +642,6 @@ HRESULT SimpleGPURenderer::UpdateVideoTexturesInternal(const VideoFrame& frame)
// NOTE: Command allocator and list are reset in ExecuteGPUPipeline() - do not reset here
// 1. Map and copy Y data
std::cout << "[SimpleGPURenderer] Starting Y data mapping..." << std::endl;
// Validate device and buffer state
if (!m_device) {
@@ -670,7 +656,6 @@ HRESULT SimpleGPURenderer::UpdateVideoTexturesInternal(const VideoFrame& frame)
// Check upload buffer description
D3D12_RESOURCE_DESC bufferDesc = yUploadBuffer->GetDesc();
std::cout << "[SimpleGPURenderer] Y buffer size: " << bufferDesc.Width << " bytes" << std::endl;
void* yMappedData = nullptr;
D3D12_RANGE readRange = { 0, 0 }; // We don't read from this resource on the CPU
@@ -685,7 +670,6 @@ HRESULT SimpleGPURenderer::UpdateVideoTexturesInternal(const VideoFrame& frame)
// Frame-specific synchronization has already been handled in RenderVideoFrame()
// No additional wait needed here - current frame allocator should be free
std::cout << "[SimpleGPURenderer] About to call Map() on Y upload buffer..." << std::endl;
hr = yUploadBuffer->Map(0, &readRange, &yMappedData);
if (FAILED(hr)) {
std::cout << "[SimpleGPURenderer] Failed to map Y upload buffer: 0x" << std::hex << hr << std::endl;
@@ -711,7 +695,6 @@ HRESULT SimpleGPURenderer::UpdateVideoTexturesInternal(const VideoFrame& frame)
const uint8_t* srcY = frame.y_plane.get();
uint8_t* dstY = static_cast<uint8_t*>(yMappedData);
std::cout << "[SimpleGPURenderer] Copying Y data: " << frame.width << "x" << frame.height << std::endl;
for (uint32_t row = 0; row < frame.height; ++row)
{
@@ -794,10 +777,11 @@ HRESULT SimpleGPURenderer::UpdateVideoTexturesInternal(const VideoFrame& frame)
dstV.pResource = vTexture.Get();
// 4.1. First transition textures to COPY_DEST state for writing
// All textures are created with PIXEL_SHADER_RESOURCE as initial state
D3D12_RESOURCE_BARRIER beforeCopyBarriers[3] = {};
beforeCopyBarriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
beforeCopyBarriers[0].Transition.pResource = yTexture.Get();
beforeCopyBarriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
beforeCopyBarriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
beforeCopyBarriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
beforeCopyBarriers[1] = beforeCopyBarriers[0];
@@ -829,7 +813,6 @@ HRESULT SimpleGPURenderer::UpdateVideoTexturesInternal(const VideoFrame& frame)
m_commandList->ResourceBarrier(3, afterCopyBarriers);
// Execute commands
std::cout << "[SimpleGPURenderer] YUV textures updated (" << frame.width << "x" << frame.height << ")" << std::endl;
return S_OK;
}
@@ -841,10 +824,10 @@ HRESULT SimpleGPURenderer::ExecuteComputeShaderInternal()
return E_FAIL;
}
HRESULT hr = S_OK;
// NOTE: Command allocator and list are reset in ExecuteGPUPipeline() - do not reset here
// Textures are already in NON_PIXEL_SHADER_RESOURCE state after upload, no transition needed
// Set compute pipeline state
m_commandList->SetComputeRootSignature(m_computeRootSignature.Get());
m_commandList->SetPipelineState(m_computePipelineState.Get());
@@ -877,8 +860,21 @@ HRESULT SimpleGPURenderer::ExecuteComputeShaderInternal()
CD3DX12_RESOURCE_BARRIER uavBarrier = CD3DX12_RESOURCE_BARRIER::UAV(m_rgbTextures[m_frameIndex].Get());
m_commandList->ResourceBarrier(1, &uavBarrier);
std::cout << "[SimpleGPURenderer] Compute shader commands recorded successfully ("
<< dispatchX << "x" << dispatchY << " thread groups)" << std::endl;
// Transition textures back to pixel shader resource state for graphics pipeline
D3D12_RESOURCE_BARRIER graphicsBarriers[3] = {};
graphicsBarriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
graphicsBarriers[0].Transition.pResource = m_yTextures[m_frameIndex].Get();
graphicsBarriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
graphicsBarriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
graphicsBarriers[1] = graphicsBarriers[0];
graphicsBarriers[1].Transition.pResource = m_uTextures[m_frameIndex].Get();
graphicsBarriers[2] = graphicsBarriers[0];
graphicsBarriers[2].Transition.pResource = m_vTextures[m_frameIndex].Get();
m_commandList->ResourceBarrier(3, graphicsBarriers);
return S_OK;
}
@@ -887,8 +883,6 @@ HRESULT SimpleGPURenderer::CopyToBackBufferInternal()
// NEW: Use graphics pipeline with AspectFit UV coordinates instead of CopyTextureRegion
// This provides proper scaling and positioning with perfect AspectFit behavior
std::cout << "[SimpleGPURenderer] CopyToBackBuffer: Using AspectFit graphics pipeline (frameIndex="
<< m_frameIndex << ")" << std::endl;
// Call the new AspectFit rendering method
return RenderWithAspectFitInternal();
@@ -922,8 +916,6 @@ void SimpleGPURenderer::WaitForFrameCompletion(UINT frameIndex)
return;
UINT64 targetValue = m_frameCompletionValues[frameIndex];
std::cout << "[SimpleGPURenderer] WaitForFrameCompletion frame " << frameIndex
<< ": target=" << targetValue << ", current=" << m_fence->GetCompletedValue() << std::endl;
if (targetValue > 0)
{
@@ -934,8 +926,6 @@ void SimpleGPURenderer::WaitForFrameCompletion(UINT frameIndex)
DWORD result = WaitForSingleObject(m_fenceEvent, 1000); // 1 second timeout
if (result == WAIT_TIMEOUT)
{
std::cout << "[SimpleGPURenderer] Frame completion timeout for frame " << frameIndex
<< ", target: " << targetValue << ", current: " << m_fence->GetCompletedValue() << std::endl;
break; // Continue anyway to prevent infinite hang
}
}
@@ -950,9 +940,9 @@ HRESULT SimpleGPURenderer::CreateComputeRootSignature()
// SRV range for input textures (Y, U, V)
ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
ranges[0].NumDescriptors = 3;
ranges[0].BaseShaderRegister = 0; // t0, t1, t2
ranges[0].BaseShaderRegister = 0;
ranges[0].RegisterSpace = 0;
ranges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC;
ranges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
ranges[0].OffsetInDescriptorsFromTableStart = 0;
// UAV range for output texture (RGB)
@@ -1010,7 +1000,6 @@ HRESULT SimpleGPURenderer::CreateComputeRootSignature()
return hr;
}
std::cout << "[SimpleGPURenderer] Compute root signature created successfully" << std::endl;
return S_OK;
}
@@ -1104,7 +1093,6 @@ void main(uint3 id : SV_DispatchThreadID)
// Store the compiled shader blob
m_computeShaderBlob = shaderBlob;
std::cout << "[SimpleGPURenderer] Compute shader compiled successfully" << std::endl;
return S_OK;
}
@@ -1130,28 +1118,9 @@ HRESULT SimpleGPURenderer::CreateComputePipelineState()
return hr;
}
std::cout << "[SimpleGPURenderer] Compute pipeline state created successfully" << std::endl;
return S_OK;
}
// Legacy public interface methods (for backward compatibility)
HRESULT SimpleGPURenderer::UpdateVideoTextures(const VideoFrame& frame)
{
std::cout << "[SimpleGPURenderer] Warning: Using legacy UpdateVideoTextures - use ExecuteGPUPipeline instead" << std::endl;
return UpdateVideoTexturesInternal(frame);
}
HRESULT SimpleGPURenderer::ExecuteComputeShader()
{
std::cout << "[SimpleGPURenderer] Warning: Using legacy ExecuteComputeShader - use ExecuteGPUPipeline instead" << std::endl;
return ExecuteComputeShaderInternal();
}
HRESULT SimpleGPURenderer::CopyToBackBuffer()
{
std::cout << "[SimpleGPURenderer] Warning: Using legacy CopyToBackBuffer - use ExecuteGPUPipeline instead" << std::endl;
return CopyToBackBufferInternal();
}
// Graphics pipeline implementation for AspectFit rendering
HRESULT SimpleGPURenderer::CreateGraphicsShaderResources()
@@ -1198,7 +1167,6 @@ HRESULT SimpleGPURenderer::CreateGraphicsShaderResources()
return hr;
}
std::cout << "[SimpleGPURenderer] Graphics shader resources created successfully" << std::endl;
return S_OK;
}
@@ -1312,7 +1280,6 @@ float4 PSMain(VSOutput input) : SV_TARGET
return hr;
}
std::cout << "[SimpleGPURenderer] Graphics shaders compiled successfully" << std::endl;
return S_OK;
}
@@ -1326,7 +1293,7 @@ HRESULT SimpleGPURenderer::CreateGraphicsRootSignature()
ranges[0].NumDescriptors = 3;
ranges[0].BaseShaderRegister = 0;
ranges[0].RegisterSpace = 0;
ranges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC;
ranges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
ranges[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
D3D12_ROOT_PARAMETER1 rootParams[2] = {};
@@ -1381,7 +1348,6 @@ HRESULT SimpleGPURenderer::CreateGraphicsRootSignature()
return hr;
}
std::cout << "[SimpleGPURenderer] Graphics root signature created successfully" << std::endl;
return S_OK;
}
@@ -1420,7 +1386,7 @@ HRESULT SimpleGPURenderer::CreateGraphicsPipelineState()
// Render target format
psoDesc.NumRenderTargets = 1;
psoDesc.RTVFormats[0] = DXGI_FORMAT_B8G8R8A8_UNORM; // SwapChain format
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; // Match SwapChain format
psoDesc.SampleMask = UINT_MAX;
psoDesc.SampleDesc.Count = 1;
@@ -1431,7 +1397,6 @@ HRESULT SimpleGPURenderer::CreateGraphicsPipelineState()
return hr;
}
std::cout << "[SimpleGPURenderer] Graphics pipeline state created successfully" << std::endl;
return S_OK;
}
@@ -1443,9 +1408,6 @@ HRESULT SimpleGPURenderer::RenderWithAspectFitInternal()
constants.containerAspectRatio = static_cast<float>(m_width) / static_cast<float>(m_height);
// Debug output for AspectFit calculation
std::cout << "[SimpleGPURenderer] AspectFit Debug: video=" << m_videoWidth << "x" << m_videoHeight
<< " (" << constants.videoAspectRatio << "), container=" << m_width << "x" << m_height
<< " (" << constants.containerAspectRatio << ")" << std::endl;
if (constants.videoAspectRatio > constants.containerAspectRatio)
{
@@ -1455,7 +1417,6 @@ HRESULT SimpleGPURenderer::RenderWithAspectFitInternal()
constants.uvOffsetX = 0.0f;
constants.uvOffsetY = 0.0f; // No offset needed - centering happens in shader
std::cout << "[SimpleGPURenderer] Video wider: scale=(" << constants.uvScaleX << "," << constants.uvScaleY << ")" << std::endl;
}
else
{
@@ -1465,7 +1426,6 @@ HRESULT SimpleGPURenderer::RenderWithAspectFitInternal()
constants.uvOffsetX = 0.0f; // No offset needed - centering happens in shader
constants.uvOffsetY = 0.0f;
std::cout << "[SimpleGPURenderer] Video taller: scale=(" << constants.uvScaleX << "," << constants.uvScaleY << ")" << std::endl;
}
// Update constant buffer
@@ -1535,9 +1495,6 @@ HRESULT SimpleGPURenderer::RenderWithAspectFitInternal()
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
m_commandList->ResourceBarrier(1, &barrier);
std::cout << "[SimpleGPURenderer] AspectFit rendering completed (scale: "
<< constants.uvScaleX << "x" << constants.uvScaleY
<< ", offset: " << constants.uvOffsetX << "," << constants.uvOffsetY << ")" << std::endl;
return S_OK;
}

View File

@@ -105,6 +105,7 @@ private:
uint32_t m_videoHeight = 0;
UINT m_rtvDescriptorSize = 0;
UINT m_srvUavDescriptorSize = 0;
uint64_t m_totalFramesRendered = 0;
// Helper methods
HRESULT CreateDevice();