From a74ccbf48f8d31877112a7aa9c0f514f25f8bbb8 Mon Sep 17 00:00:00 2001 From: turanszkij Date: Sat, 18 Aug 2018 16:30:10 +0100 Subject: [PATCH] graphicsdevice can now download textures too + resurrected wiHelper::screenshot() function --- WickedEngine/Utility/utility_common.cpp | 3 +- WickedEngine/wiEmittedParticle.cpp | 2 +- WickedEngine/wiGraphicsDevice.cpp | 2 + WickedEngine/wiGraphicsDevice.h | 4 +- WickedEngine/wiGraphicsDevice_DX11.cpp | 75 +++++++++++++++++++----- WickedEngine/wiGraphicsDevice_DX11.h | 2 +- WickedEngine/wiGraphicsDevice_DX12.cpp | 2 +- WickedEngine/wiGraphicsDevice_DX12.h | 2 +- WickedEngine/wiGraphicsDevice_Vulkan.cpp | 2 +- WickedEngine/wiGraphicsDevice_Vulkan.h | 2 +- WickedEngine/wiHelper.cpp | 62 +++++++++++++++----- 11 files changed, 119 insertions(+), 39 deletions(-) diff --git a/WickedEngine/Utility/utility_common.cpp b/WickedEngine/Utility/utility_common.cpp index f208c7fbe..4c2f177e8 100644 --- a/WickedEngine/Utility/utility_common.cpp +++ b/WickedEngine/Utility/utility_common.cpp @@ -2,6 +2,7 @@ #define _CRT_SECURE_NO_WARNINGS #define STB_IMAGE_IMPLEMENTATION -#define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image_write.h" diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index 21f8935a6..790a55406 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -647,7 +647,7 @@ void wiEmittedParticle::UpdateRenderData(GRAPHICSTHREAD threadID) if (DEBUG) { - device->DownloadBuffer(counterBuffer, debugDataReadbackBuffer, &debugData, threadID); + device->DownloadResource(counterBuffer, debugDataReadbackBuffer, &debugData, threadID); } } diff --git a/WickedEngine/wiGraphicsDevice.cpp b/WickedEngine/wiGraphicsDevice.cpp index 07f5d176a..ec7fed947 100644 --- a/WickedEngine/wiGraphicsDevice.cpp +++ b/WickedEngine/wiGraphicsDevice.cpp @@ -37,6 +37,7 @@ uint32_t GraphicsDevice::GetFormatStride(FORMAT value) case FORMAT_R32G32_FLOAT: return 8; break; + case FORMAT_R11G11B10_FLOAT: case FORMAT_R16G16_FLOAT: case FORMAT_R32_FLOAT: case FORMAT_R32_UINT: @@ -44,6 +45,7 @@ uint32_t GraphicsDevice::GetFormatStride(FORMAT value) case FORMAT_R8G8B8A8_SINT: case FORMAT_R8G8B8A8_UNORM: case FORMAT_R8G8B8A8_SNORM: + case FORMAT_R10G10B10A2_UNORM: return 4; break; case FORMAT_R16_FLOAT: diff --git a/WickedEngine/wiGraphicsDevice.h b/WickedEngine/wiGraphicsDevice.h index 5576d6b43..5e62fcabf 100644 --- a/WickedEngine/wiGraphicsDevice.h +++ b/WickedEngine/wiGraphicsDevice.h @@ -23,7 +23,7 @@ namespace wiGraphicsTypes bool TESSELLATION, MULTITHREADED_RENDERING, CONSERVATIVE_RASTERIZATION, RASTERIZER_ORDERED_VIEWS, UNORDEREDACCESSTEXTURE_LOAD_EXT; public: GraphicsDevice() - :FRAMECOUNT(0), VSYNC(true), SCREENWIDTH(0), SCREENHEIGHT(0), FULLSCREEN(false), RESOLUTIONCHANGED(false), BACKBUFFER_FORMAT(FORMAT_R10G10B10A2_UNORM), + :FRAMECOUNT(0), VSYNC(true), SCREENWIDTH(0), SCREENHEIGHT(0), FULLSCREEN(false), RESOLUTIONCHANGED(false), BACKBUFFER_FORMAT(FORMAT_R8G8B8A8_UNORM/*FORMAT_R10G10B10A2_UNORM*/), TESSELLATION(false), MULTITHREADED_RENDERING(false), CONSERVATIVE_RASTERIZATION(false),RASTERIZER_ORDERED_VIEWS(false), UNORDEREDACCESSTEXTURE_LOAD_EXT(false) {} @@ -145,7 +145,7 @@ namespace wiGraphicsTypes virtual void UpdateBuffer(GPUBuffer* buffer, const void* data, GRAPHICSTHREAD threadID, int dataSize = -1) = 0; virtual void* AllocateFromRingBuffer(GPURingBuffer* buffer, size_t dataSize, UINT& offsetIntoBuffer, GRAPHICSTHREAD threadID) = 0; virtual void InvalidateBufferAccess(GPUBuffer* buffer, GRAPHICSTHREAD threadID) = 0; - virtual bool DownloadBuffer(GPUBuffer* bufferToDownload, GPUBuffer* bufferDest, void* dataDest, GRAPHICSTHREAD threadID) = 0; + virtual bool DownloadResource(GPUResource* resourceToDownload, GPUResource* resourceDest, void* dataDest, GRAPHICSTHREAD threadID) = 0; virtual void QueryBegin(GPUQuery *query, GRAPHICSTHREAD threadID) = 0; virtual void QueryEnd(GPUQuery *query, GRAPHICSTHREAD threadID) = 0; virtual bool QueryRead(GPUQuery *query, GRAPHICSTHREAD threadID) = 0; diff --git a/WickedEngine/wiGraphicsDevice_DX11.cpp b/WickedEngine/wiGraphicsDevice_DX11.cpp index 91936ff99..f7dbe47b7 100644 --- a/WickedEngine/wiGraphicsDevice_DX11.cpp +++ b/WickedEngine/wiGraphicsDevice_DX11.cpp @@ -1581,6 +1581,11 @@ Texture2D GraphicsDevice_DX11::GetBackBuffer() Texture2D result; result.resource_DX11 = (wiCPUHandle)backBuffer; backBuffer->AddRef(); + + D3D11_TEXTURE2D_DESC desc; + backBuffer->GetDesc(&desc); + result.desc = _ConvertTextureDesc_Inv(&desc); + return result; } @@ -3639,24 +3644,66 @@ void GraphicsDevice_DX11::InvalidateBufferAccess(GPUBuffer* buffer, GRAPHICSTHRE { deviceContexts[threadID]->Unmap((ID3D11Resource*)buffer->resource_DX11, 0); } -bool GraphicsDevice_DX11::DownloadBuffer(GPUBuffer* bufferToDownload, GPUBuffer* bufferDest, void* dataDest, GRAPHICSTHREAD threadID) +bool GraphicsDevice_DX11::DownloadResource(GPUResource* resourceToDownload, GPUResource* resourceDest, void* dataDest, GRAPHICSTHREAD threadID) { - assert(bufferToDownload->desc.ByteWidth <= bufferDest->desc.ByteWidth); - assert(bufferDest->desc.Usage & USAGE_STAGING); - assert(dataDest != nullptr); - - deviceContexts[threadID]->CopyResource((ID3D11Resource*)bufferDest->resource_DX11, (ID3D11Resource*)bufferToDownload->resource_DX11); - - D3D11_MAPPED_SUBRESOURCE mappedResource = {}; - HRESULT hr = deviceContexts[threadID]->Map((ID3D11Resource*)bufferDest->resource_DX11, 0, D3D11_MAP_READ, /*async ? D3D11_MAP_FLAG_DO_NOT_WAIT :*/ 0, &mappedResource); - bool result = SUCCEEDED(hr); - if (result) + // Download Buffer: { - memcpy(dataDest, mappedResource.pData, bufferToDownload->desc.ByteWidth); - deviceContexts[threadID]->Unmap((ID3D11Resource*)bufferDest->resource_DX11, 0); + GPUBuffer* bufferToDownload = dynamic_cast(resourceToDownload); + GPUBuffer* bufferDest = dynamic_cast(resourceDest); + + if (bufferToDownload != nullptr && bufferDest != nullptr) + { + assert(bufferToDownload->desc.ByteWidth <= bufferDest->desc.ByteWidth); + assert(bufferDest->desc.Usage & USAGE_STAGING); + assert(dataDest != nullptr); + + deviceContexts[threadID]->CopyResource((ID3D11Resource*)bufferDest->resource_DX11, (ID3D11Resource*)bufferToDownload->resource_DX11); + + D3D11_MAPPED_SUBRESOURCE mappedResource = {}; + HRESULT hr = deviceContexts[threadID]->Map((ID3D11Resource*)bufferDest->resource_DX11, 0, D3D11_MAP_READ, /*async ? D3D11_MAP_FLAG_DO_NOT_WAIT :*/ 0, &mappedResource); + bool result = SUCCEEDED(hr); + if (result) + { + memcpy(dataDest, mappedResource.pData, bufferToDownload->desc.ByteWidth); + deviceContexts[threadID]->Unmap((ID3D11Resource*)bufferDest->resource_DX11, 0); + } + + return result; + } } - return result; + // Download Texture: + { + Texture* textureToDownload = dynamic_cast(resourceToDownload); + Texture* textureDest = dynamic_cast(resourceDest); + + if (textureToDownload != nullptr && textureDest != nullptr) + { + assert(textureToDownload->desc.Width <= textureDest->desc.Width); + assert(textureToDownload->desc.Height <= textureDest->desc.Height); + assert(textureToDownload->desc.Depth <= textureDest->desc.Depth); + assert(textureDest->desc.Usage & USAGE_STAGING); + assert(dataDest != nullptr); + + deviceContexts[threadID]->CopyResource((ID3D11Resource*)textureDest->resource_DX11, (ID3D11Resource*)textureToDownload->resource_DX11); + + D3D11_MAPPED_SUBRESOURCE mappedResource = {}; + HRESULT hr = deviceContexts[threadID]->Map((ID3D11Resource*)textureDest->resource_DX11, 0, D3D11_MAP_READ, 0, &mappedResource); + bool result = SUCCEEDED(hr); + if (result) + { + UINT cpycount = max(1, textureToDownload->desc.Width) * max(1, textureToDownload->desc.Height) * max(1, textureToDownload->desc.Depth); + UINT cpystride = GetFormatStride(textureToDownload->desc.Format); + UINT cpysize = cpycount * cpystride; + memcpy(dataDest, mappedResource.pData, cpysize); + deviceContexts[threadID]->Unmap((ID3D11Resource*)textureDest->resource_DX11, 0); + } + + return result; + } + } + + return false; } void GraphicsDevice_DX11::WaitForGPU() diff --git a/WickedEngine/wiGraphicsDevice_DX11.h b/WickedEngine/wiGraphicsDevice_DX11.h index 98904d4d9..529928434 100644 --- a/WickedEngine/wiGraphicsDevice_DX11.h +++ b/WickedEngine/wiGraphicsDevice_DX11.h @@ -149,7 +149,7 @@ namespace wiGraphicsTypes virtual void UpdateBuffer(GPUBuffer* buffer, const void* data, GRAPHICSTHREAD threadID, int dataSize = -1) override; virtual void* AllocateFromRingBuffer(GPURingBuffer* buffer, size_t dataSize, UINT& offsetIntoBuffer, GRAPHICSTHREAD threadID) override; virtual void InvalidateBufferAccess(GPUBuffer* buffer, GRAPHICSTHREAD threadID) override; - virtual bool DownloadBuffer(GPUBuffer* bufferToDownload, GPUBuffer* bufferDest, void* dataDest, GRAPHICSTHREAD threadID) override; + virtual bool DownloadResource(GPUResource* resourceToDownload, GPUResource* resourceDest, void* dataDest, GRAPHICSTHREAD threadID) override; virtual void QueryBegin(GPUQuery *query, GRAPHICSTHREAD threadID) override; virtual void QueryEnd(GPUQuery *query, GRAPHICSTHREAD threadID) override; virtual bool QueryRead(GPUQuery *query, GRAPHICSTHREAD threadID) override; diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index 7c8a952be..00765a716 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -3908,7 +3908,7 @@ namespace wiGraphicsTypes void GraphicsDevice_DX12::InvalidateBufferAccess(GPUBuffer* buffer, GRAPHICSTHREAD threadID) { } - bool GraphicsDevice_DX12::DownloadBuffer(GPUBuffer* bufferToDownload, GPUBuffer* bufferDest, void* dataDest, GRAPHICSTHREAD threadID) + bool GraphicsDevice_DX12::DownloadResource(GPUResource* resourceToDownload, GPUResource* resourceDest, void* dataDest, GRAPHICSTHREAD threadID) { return false; } diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h index c4f360f1e..80beb14f9 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.h +++ b/WickedEngine/wiGraphicsDevice_DX12.h @@ -241,7 +241,7 @@ namespace wiGraphicsTypes virtual void UpdateBuffer(GPUBuffer* buffer, const void* data, GRAPHICSTHREAD threadID, int dataSize = -1) override; virtual void* AllocateFromRingBuffer(GPURingBuffer* buffer, size_t dataSize, UINT& offsetIntoBuffer, GRAPHICSTHREAD threadID) override; virtual void InvalidateBufferAccess(GPUBuffer* buffer, GRAPHICSTHREAD threadID) override; - virtual bool DownloadBuffer(GPUBuffer* bufferToDownload, GPUBuffer* bufferDest, void* dataDest, GRAPHICSTHREAD threadID) override; + virtual bool DownloadResource(GPUResource* resourceToDownload, GPUResource* resourceDest, void* dataDest, GRAPHICSTHREAD threadID) override; virtual void QueryBegin(GPUQuery *query, GRAPHICSTHREAD threadID) override; virtual void QueryEnd(GPUQuery *query, GRAPHICSTHREAD threadID) override; virtual bool QueryRead(GPUQuery *query, GRAPHICSTHREAD threadID) override; diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index f79daae2f..3c5ea500a 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -5157,7 +5157,7 @@ namespace wiGraphicsTypes { //vkUnmapMemory(device, static_cast(buffer->resourceMemory_Vulkan)); } - bool GraphicsDevice_Vulkan::DownloadBuffer(GPUBuffer* bufferToDownload, GPUBuffer* bufferDest, void* dataDest, GRAPHICSTHREAD threadID) + bool GraphicsDevice_Vulkan::DownloadResource(GPUResource* resourceToDownload, GPUResource* resourceDest, void* dataDest, GRAPHICSTHREAD threadID) { return false; } diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index d23f1d32d..006692b39 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -281,7 +281,7 @@ namespace wiGraphicsTypes virtual void UpdateBuffer(GPUBuffer* buffer, const void* data, GRAPHICSTHREAD threadID, int dataSize = -1) override; virtual void* AllocateFromRingBuffer(GPURingBuffer* buffer, size_t dataSize, UINT& offsetIntoBuffer, GRAPHICSTHREAD threadID) override; virtual void InvalidateBufferAccess(GPUBuffer* buffer, GRAPHICSTHREAD threadID) override; - virtual bool DownloadBuffer(GPUBuffer* bufferToDownload, GPUBuffer* bufferDest, void* dataDest, GRAPHICSTHREAD threadID) override; + virtual bool DownloadResource(GPUResource* resourceToDownload, GPUResource* resourceDest, void* dataDest, GRAPHICSTHREAD threadID) override; virtual void QueryBegin(GPUQuery *query, GRAPHICSTHREAD threadID) override; virtual void QueryEnd(GPUQuery *query, GRAPHICSTHREAD threadID) override; virtual bool QueryRead(GPUQuery *query, GRAPHICSTHREAD threadID) override; diff --git a/WickedEngine/wiHelper.cpp b/WickedEngine/wiHelper.cpp index da6427af2..1ab2a714a 100644 --- a/WickedEngine/wiHelper.cpp +++ b/WickedEngine/wiHelper.cpp @@ -3,6 +3,8 @@ #include "wiBackLog.h" #include "wiWindowRegistration.h" +#include "Utility/stb_image_write.h" + #include #include #include @@ -74,22 +76,50 @@ namespace wiHelper void screenshot(const std::string& name) { - //CreateDirectoryA("screenshots", 0); - //stringstream ss(""); - //if (name.length() <= 0) - // ss << GetOriginalWorkingDirectory() << "screenshots/sc_" << getCurrentDateTimeAsString() << ".png"; - //else - // ss << name; - //if (SUCCEEDED(wiRenderer::GetDevice()->SaveTexturePNG(ss.str(), &wiRenderer::GetDevice()->GetBackBuffer(), GRAPHICSTHREAD_IMMEDIATE))) - //{ - // ss << " Saved successfully!"; - // wiBackLog::post(ss.str().c_str()); - //} - //else - //{ - // wiBackLog::post("Screenshot failed"); - //} - messageBox("Please reimplement wiHelper::screenshot functionality!"); + CreateDirectoryA("screenshots", 0); + stringstream ss(""); + if (name.length() <= 0) + ss << GetOriginalWorkingDirectory() << "screenshots/sc_" << getCurrentDateTimeAsString() << ".jpg"; + else + ss << name; + + using namespace wiGraphicsTypes; + + GraphicsDevice* device = wiRenderer::GetDevice(); + + device->WaitForGPU(); + + static Texture2D tex = device->GetBackBuffer(); + TextureDesc desc = tex.GetDesc(); + UINT data_count = desc.Width * desc.Height; + UINT data_stride = device->GetFormatStride(desc.Format); + UINT data_size = data_count * data_stride; + + static unsigned char* data = nullptr; + static Texture2D* stagingTex = nullptr; + if (stagingTex == nullptr) + { + TextureDesc staging_desc = desc; + staging_desc.Usage = USAGE_STAGING; + staging_desc.CPUAccessFlags = CPU_ACCESS_READ; + staging_desc.BindFlags = 0; + staging_desc.MiscFlags = 0; + HRESULT hr = device->CreateTexture2D(&staging_desc, nullptr, &stagingTex); + assert(SUCCEEDED(hr)); + + data = new unsigned char[data_size]; + } + + bool download_success = device->DownloadResource(&tex, stagingTex, data, GRAPHICSTHREAD_IMMEDIATE); + assert(download_success); + + // TODO: png would be better, but it has some problems now... + + //int write_result = stbi_write_png(ss.str().c_str(), (int)desc.Width, (int)desc.Height, 4, data, (int)data_stride); + int write_result = stbi_write_jpg(ss.str().c_str(), (int)desc.Width, (int)desc.Height, 4, data, 100); + //int write_result = stbi_write_bmp(ss.str().c_str(), (int)desc.Width, (int)desc.Height, 4, data); + assert(write_result); + } string getCurrentDateTimeAsString()