From 7fa3ab2442dfbd60e7ec8688558d764a29ec8d89 Mon Sep 17 00:00:00 2001 From: ened Date: Tue, 23 Sep 2025 02:56:01 +0900 Subject: [PATCH] Fix D3D12 runtime errors --- .../src/Rendering/SimpleGPURenderer.cpp | 103 +++++------------- .../src/Rendering/SimpleGPURenderer.h | 1 + 2 files changed, 31 insertions(+), 73 deletions(-) diff --git a/vav2/Vav2Player/Vav2Player/src/Rendering/SimpleGPURenderer.cpp b/vav2/Vav2Player/Vav2Player/src/Rendering/SimpleGPURenderer.cpp index bd8a973..5b7b2b7 100644 --- a/vav2/Vav2Player/Vav2Player/src/Rendering/SimpleGPURenderer.cpp +++ b/vav2/Vav2Player/Vav2Player/src/Rendering/SimpleGPURenderer.cpp @@ -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(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(m_width) / static_cast(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; } diff --git a/vav2/Vav2Player/Vav2Player/src/Rendering/SimpleGPURenderer.h b/vav2/Vav2Player/Vav2Player/src/Rendering/SimpleGPURenderer.h index 1cd2797..ace21fc 100644 --- a/vav2/Vav2Player/Vav2Player/src/Rendering/SimpleGPURenderer.h +++ b/vav2/Vav2Player/Vav2Player/src/Rendering/SimpleGPURenderer.h @@ -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();