diff options
| author | Yong He <yonghe@outlook.com> | 2017-10-24 19:14:14 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-10-24 19:14:14 -0400 |
| commit | 3043171dae37d18015d6cd26287d492c576f4f1a (patch) | |
| tree | 1037732c1e90afd36b588851ce5755d64188bcdb /tools/render-test | |
| parent | ab64cf2ec05980d72cb2bad45e629d10ebbefdc1 (diff) | |
| parent | 434d3428932ccaa0f6834d03c37adcab37d17a01 (diff) | |
Merge pull request #227 from csyonghe/master
Extending render-test to support various resource inputs
Diffstat (limited to 'tools/render-test')
| -rw-r--r-- | tools/render-test/main.cpp | 49 | ||||
| -rw-r--r-- | tools/render-test/render-d3d11.cpp | 480 | ||||
| -rw-r--r-- | tools/render-test/render-gl.cpp | 15 | ||||
| -rw-r--r-- | tools/render-test/render-test.vcxproj | 13 | ||||
| -rw-r--r-- | tools/render-test/render-test.vcxproj.filters | 6 | ||||
| -rw-r--r-- | tools/render-test/render.h | 9 | ||||
| -rw-r--r-- | tools/render-test/shader-input-layout.cpp | 221 | ||||
| -rw-r--r-- | tools/render-test/shader-input-layout.h | 61 |
8 files changed, 786 insertions, 68 deletions
diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp index 6907ba40f..d3247e55f 100644 --- a/tools/render-test/main.cpp +++ b/tools/render-test/main.cpp @@ -5,7 +5,7 @@ #include "render-d3d11.h" #include "render-gl.h" #include "slang-support.h" - +#include "shader-input-layout.h" #include <stdio.h> #include <stdlib.h> @@ -54,8 +54,9 @@ uintptr_t gConstantBufferSize, gComputeResultBufferSize; Buffer* gConstantBuffer; InputLayout* gInputLayout; Buffer* gVertexBuffer; -Buffer* gComputeResultBuffer; -ShaderProgram* gShaderProgram; +ShaderProgram* gShaderProgram; +BindingState* gBindingState; +ShaderInputLayout gShaderInputLayout; // Entry point name to use for vertex/fragment shader static char const* vertexEntryPointName = "vertexMain"; @@ -92,6 +93,8 @@ Error initializeShaders( fclose(sourceFile); sourceText[sourceSize] = 0; + gShaderInputLayout.Parse(sourceText); + ShaderCompileRequest::SourceInfo sourceInfo; sourceInfo.path = sourcePath; sourceInfo.text = sourceText; @@ -121,16 +124,6 @@ Error initializeShaders( return Error::None; } - -void outputComputeResult(Renderer* renderer, const char * fileName) -{ - float* data = (float*)renderer->map(gComputeResultBuffer, MapFlavor::HostRead); - FILE* f = fopen(fileName, "wt"); - for (auto i = 0u; i < gComputeResultBufferSize / sizeof(UInt); i++) - fprintf(f, "%.9g\n", data[i]); - fclose(f); -} - // // At initialization time, we are going to load and compile our Slang shader // code, and then create the D3D11 API objects we need for rendering. @@ -144,6 +137,7 @@ Error initializeInner( err = initializeShaders(shaderCompiler); if(err != Error::None) return err; + gBindingState = renderer->createBindingState(gShaderInputLayout); // Do other initialization that doesn't depend on the source language. @@ -157,20 +151,7 @@ Error initializeInner( gConstantBuffer = renderer->createBuffer(constantBufferDesc); if(!gConstantBuffer) return Error::Unexpected; - - gComputeResultBufferSize = 512 * sizeof(float); - BufferDesc computeResultBufferDesc; - computeResultBufferDesc.size = gComputeResultBufferSize; - computeResultBufferDesc.flavor = BufferFlavor::Storage; - gComputeResultBuffer = renderer->createBuffer(computeResultBufferDesc); - if (!gComputeResultBufferSize) - return Error::Unexpected; - // initialize buffer to 0 - char * ptr = (char*)renderer->map(gComputeResultBuffer, MapFlavor::HostWrite); - for (auto i = 0u; i < gComputeResultBufferSize; i++) - ptr[i] = 0; - renderer->unmap(gComputeResultBuffer); - + // Input Assembler (IA) InputElementDesc inputElements[] = { @@ -222,7 +203,7 @@ void renderFrameInner( renderer->setShaderProgram(gShaderProgram); renderer->setConstantBuffer(0, gConstantBuffer); - + renderer->setBindingState(gBindingState); // renderer->draw(3); @@ -231,7 +212,7 @@ void renderFrameInner( void runCompute(Renderer * renderer) { renderer->setShaderProgram(gShaderProgram); - renderer->setStorageBuffer(0, gComputeResultBuffer); + renderer->setBindingState(gBindingState); renderer->dispatchCompute(1, 1, 1); } @@ -403,7 +384,7 @@ int main( { if (message.message == WM_QUIT) { - return (int)message.wParam; + return (int)message.wParam; } TranslateMessage(&message); @@ -428,10 +409,10 @@ int main( // If we are in a mode where output is requested, we need to snapshot the back buffer here if (gOptions.outputPath) { - if (gOptions.shaderType == ShaderProgramType::Compute) - outputComputeResult(renderer, gOptions.outputPath); - else - renderer->captureScreenShot(gOptions.outputPath); + if (gOptions.shaderType == ShaderProgramType::Compute) + renderer->serializeOutput(gBindingState, gOptions.outputPath); + else + renderer->captureScreenShot(gOptions.outputPath); return 0; } diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp index 6e9e04a78..8f73b4dd4 100644 --- a/tools/render-test/render-d3d11.cpp +++ b/tools/render-test/render-d3d11.cpp @@ -36,9 +36,26 @@ #endif #endif // +using namespace Slang; namespace renderer_test { +struct D3DBinding +{ + ShaderInputType type; + ID3D11ShaderResourceView * srv = nullptr; + ID3D11UnorderedAccessView * uav = nullptr; + ID3D11Buffer * buffer = nullptr; + ID3D11SamplerState * samplerState = nullptr; + int binding = 0; + bool isOutput = false; + int bufferLength = 0; +}; +struct D3DBindingState +{ + List<D3DBinding> bindings; +}; + // @@ -246,12 +263,12 @@ public: ID3D11Device* dxDevice = NULL; ID3D11DeviceContext* dxImmediateContext = NULL; ID3D11Texture2D* dxBackBufferTexture = NULL; - ID3D11RenderTargetView* dxBackBufferRTV = NULL; - + List<ID3D11RenderTargetView*> dxRenderTargetViews; + List<ID3D11Texture2D *> dxRenderTargetTextures; + D3DBindingState * currentBindings = nullptr; virtual void initialize(void* inWindowHandle) override { auto windowHandle = (HWND) inWindowHandle; - // Rather than statically link against D3D, we load it dynamically. HMODULE d3d11 = LoadLibraryA("d3d11.dll"); @@ -321,10 +338,8 @@ public: { hr = D3D11CreateDeviceAndSwapChain_( NULL, // adapter (use default) - D3D_DRIVER_TYPE_WARP, -// D3D_DRIVER_TYPE_HARDWARE, - +// D3D_DRIVER_TYPE_HARDWARE, NULL, // software deviceFlags, &featureLevels[ii], @@ -352,21 +367,36 @@ public: static const IID kIID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c }; + dxSwapChain->GetBuffer( 0, kIID_ID3D11Texture2D, (void**)&dxBackBufferTexture); - dxDevice->CreateRenderTargetView( - dxBackBufferTexture, - NULL, - &dxBackBufferRTV); + for (int i = 0; i < 8; i++) + { + ID3D11Texture2D* texture; + D3D11_TEXTURE2D_DESC textureDesc; + dxBackBufferTexture->GetDesc(&textureDesc); + dxDevice->CreateTexture2D(&textureDesc, nullptr, &texture); + ID3D11RenderTargetView * rtv; + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + rtvDesc.Texture2D.MipSlice = 0; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + dxDevice->CreateRenderTargetView( + texture, + &rtvDesc, + &rtv); + dxRenderTargetViews.Add(rtv); + dxRenderTargetTextures.Add(texture); + } // We immediately bind the back-buffer render target view, and we aren't // going to switch. We don't bother with a depth buffer. dxImmediateContext->OMSetRenderTargets( - 1, - &dxBackBufferRTV, + dxRenderTargetViews.Count(), + dxRenderTargetViews.Buffer(), NULL); // Similarly, we are going to set up a viewport once, and then never @@ -389,13 +419,15 @@ public: virtual void clearFrame() override { - dxImmediateContext->ClearRenderTargetView( - dxBackBufferRTV, - clearColor); + for (auto i = 0u; i < dxRenderTargetViews.Count(); i++) + dxImmediateContext->ClearRenderTargetView( + dxRenderTargetViews[i], + clearColor); } virtual void presentFrame() override { + dxImmediateContext->CopyResource(dxBackBufferTexture, dxRenderTargetTextures[0]); dxSwapChain->Present(0, 0); } @@ -404,7 +436,7 @@ public: HRESULT hr = captureTextureToFile( dxDevice, dxImmediateContext, - dxBackBufferTexture, + dxRenderTargetTextures[0], outputPath); if( FAILED(hr) ) { @@ -558,24 +590,24 @@ public: return (InputLayout*) dxInputLayout; } - virtual void* map(Buffer* buffer, MapFlavor flavor) override + void* map(ID3D11Buffer * buffer, MapFlavor flavor) { auto dxContext = dxImmediateContext; - auto dxBuffer = ((D3DBuffer*)buffer)->buffer; + auto dxBuffer = buffer; D3D11_MAP dxMapFlavor; - switch( flavor ) + switch (flavor) { case MapFlavor::WriteDiscard: dxMapFlavor = D3D11_MAP_WRITE_DISCARD; break; - case MapFlavor::HostWrite: - dxMapFlavor = D3D11_MAP_WRITE; - break; - case MapFlavor::HostRead: - dxMapFlavor = D3D11_MAP_READ; - break; + case MapFlavor::HostWrite: + dxMapFlavor = D3D11_MAP_WRITE; + break; + case MapFlavor::HostRead: + dxMapFlavor = D3D11_MAP_READ; + break; default: return nullptr; } @@ -585,19 +617,27 @@ public: // per-frame (we always use an identity projection). D3D11_MAPPED_SUBRESOURCE dxMapped; HRESULT hr = dxContext->Map(dxBuffer, 0, dxMapFlavor, 0, &dxMapped); - if(FAILED(hr)) + if (FAILED(hr)) return nullptr; return dxMapped.pData; } - virtual void unmap(Buffer* buffer) override + virtual void* map(Buffer* buffer, MapFlavor flavor) override + { + return map(((D3DBuffer*)buffer)->buffer, flavor); + } + + void unmap(ID3D11Buffer * buffer) { auto dxContext = dxImmediateContext; + dxContext->Unmap(buffer, 0); + } + virtual void unmap(Buffer* buffer) override + { auto dxBuffer = ((D3DBuffer*)buffer)->buffer; - - dxContext->Unmap(dxBuffer, 0); + unmap(dxBuffer); } virtual void setInputLayout(InputLayout* inputLayout) override @@ -686,7 +726,7 @@ public: virtual void draw(UInt vertexCount, UInt startVertex) override { auto dxContext = dxImmediateContext; - + applyBindingState(false); dxContext->Draw((UINT) vertexCount, (UINT) startVertex); } @@ -749,8 +789,388 @@ public: virtual void dispatchCompute(int x, int y, int z) override { auto dxContext = dxImmediateContext; + applyBindingState(true); dxContext->Dispatch(x, y, z); } + + void createInputBuffer( + InputBufferDesc & bufferDesc, + List<unsigned int> & bufferData, + ID3D11Buffer * &bufferOut, + ID3D11UnorderedAccessView * &viewOut, + ID3D11ShaderResourceView * &srvOut) + { + auto dxContext = dxImmediateContext; + D3D11_BUFFER_DESC desc = {0}; + desc.ByteWidth = bufferData.Count() * sizeof(unsigned int); + if (bufferDesc.type == InputBufferType::ConstantBuffer) + { + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER | D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + } + else + { + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + if (bufferDesc.stride != 0) + { + desc.StructureByteStride = bufferDesc.stride; + desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; + } + else + { + desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + } + } + D3D11_SUBRESOURCE_DATA data = {0}; + data.pSysMem = bufferData.Buffer(); + dxDevice->CreateBuffer(&desc, &data, &bufferOut); + int elemSize = bufferDesc.stride <= 0 ? 1 : bufferDesc.stride; + if (bufferDesc.type == InputBufferType::StorageBuffer) + { + D3D11_UNORDERED_ACCESS_VIEW_DESC viewDesc; + memset(&viewDesc, 0, sizeof(viewDesc)); + viewDesc.Buffer.FirstElement = 0; + viewDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize); + viewDesc.Buffer.Flags = 0; + viewDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + viewDesc.Format = DXGI_FORMAT_UNKNOWN; + dxDevice->CreateUnorderedAccessView(bufferOut, &viewDesc, &viewOut); + } + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + memset(&srvDesc, 0, sizeof(srvDesc)); + srvDesc.Buffer.FirstElement = 0; + srvDesc.Buffer.ElementWidth = elemSize; + srvDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize); + srvDesc.Buffer.ElementOffset = 0; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + srvDesc.Format = DXGI_FORMAT_UNKNOWN; + dxDevice->CreateShaderResourceView(bufferOut, &srvDesc, &srvOut); + } + + void createInputTexture(const InputTextureDesc & inputDesc, ID3D11ShaderResourceView * &viewOut) + { + int arrLen = inputDesc.arrayLength; + if (arrLen == 0) + arrLen = 1; + List<D3D11_SUBRESOURCE_DATA> subRes; + List<List<unsigned int>> dataBuffer; + int arraySize = arrLen; + if (inputDesc.isCube) + arraySize *= 6; + int textureSize = inputDesc.size; + int textureMipLevels = Math::Log2Floor(textureSize) + 1; + subRes.SetSize(textureMipLevels * arraySize); + dataBuffer.SetSize(subRes.Count()); + + auto iteratePixels = [&](int dimension, int size, unsigned int * buffer, auto f) + { + if (dimension == 1) + for (int i = 0; i < size; i++) + buffer[i] = f(i, 0, 0); + else if (dimension == 2) + for (int i = 0; i < size; i++) + for (int j = 0; j < size; j++) + buffer[i*size + j] = f(j, i, 0); + else if (dimension == 3) + for (int i = 0; i < size; i++) + for (int j = 0; j < size; j++) + for (int k = 0; k < size; k++) + buffer[i*size*size + j*size + k] = f(k, j, i); + }; + + int slice = 0; + for (int i = 0; i < arraySize; i++) + { + for (int j = 0; j < textureMipLevels; j++) + { + int size = textureSize >> j; + int bufferLen = size; + if (inputDesc.dimension == 2) + bufferLen *= size; + else if (inputDesc.dimension == 3) + bufferLen *= size*size; + dataBuffer[slice].SetSize(bufferLen); + subRes[slice].pSysMem = dataBuffer[slice].Buffer(); + subRes[slice].SysMemPitch = sizeof(unsigned int) * size; + subRes[slice].SysMemSlicePitch = sizeof(unsigned int) * size * size; + + iteratePixels(inputDesc.dimension, size, dataBuffer[slice].Buffer(), [&](int x, int y, int z) -> unsigned int + { + if (inputDesc.content == InputTextureContent::Zero) + { + return 0x0; + } + else if (inputDesc.content == InputTextureContent::One) + { + return 0xFFFFFFFF; + } + else if (inputDesc.content == InputTextureContent::Gradient) + { + unsigned char r = (unsigned char)(x / (float)(size - 1) * 255.0f); + unsigned char g = (unsigned char)(y / (float)(size - 1) * 255.0f); + unsigned char b = (unsigned char)(z / (float)(size - 1) * 255.0f); + return 0xFF000000 + r + (g << 8) + (b << 16); + } + else if (inputDesc.content == InputTextureContent::ChessBoard) + { + unsigned int xSig = x < (size >> 1) ? 1 : 0; + unsigned int ySig = y < (size >> 1) ? 1 : 0; + unsigned int zSig = z < (size >> 1) ? 1 : 0; + auto sig = xSig ^ ySig ^ zSig; + if (sig) + return 0xFFFFFFFF; + else + return 0xFF808080; + } + return 0x0; + }); + slice++; + } + } + if (inputDesc.dimension == 1) + { + D3D11_TEXTURE1D_DESC desc = { 0 }; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET | D3D11_BIND_UNORDERED_ACCESS; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; + desc.MipLevels = textureMipLevels; + desc.ArraySize = arraySize; + desc.Width = textureSize; + desc.Usage = D3D11_USAGE_DEFAULT; + + ID3D11Texture1D * texture; + dxDevice->CreateTexture1D(&desc, subRes.Buffer(), &texture); + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; + if (inputDesc.arrayLength != 0) + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY; + viewDesc.Texture1D.MipLevels = textureMipLevels; + viewDesc.Texture1D.MostDetailedMip = 0; + viewDesc.Texture1DArray.ArraySize = arraySize; + viewDesc.Texture1DArray.FirstArraySlice = 0; + viewDesc.Texture1DArray.MipLevels = textureMipLevels; + viewDesc.Texture1DArray.MostDetailedMip = 0; + dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut); + } + else if (inputDesc.dimension == 2) + { + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + D3D11_TEXTURE2D_DESC desc = { 0 }; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET | D3D11_BIND_UNORDERED_ACCESS; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; + desc.MipLevels = textureMipLevels; + desc.ArraySize = arraySize; + if (inputDesc.isCube) + { + desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + viewDesc.TextureCube.MipLevels = textureMipLevels; + viewDesc.TextureCube.MostDetailedMip = 0; + viewDesc.TextureCubeArray.MipLevels = textureMipLevels; + viewDesc.TextureCubeArray.MostDetailedMip = 0; + viewDesc.TextureCubeArray.First2DArrayFace = 0; + viewDesc.TextureCubeArray.NumCubes = inputDesc.arrayLength; + } + else + { + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + viewDesc.Texture2D.MipLevels = textureMipLevels; + viewDesc.Texture2D.MostDetailedMip = 0; + viewDesc.Texture2DArray.ArraySize = arraySize; + viewDesc.Texture2DArray.FirstArraySlice = 0; + viewDesc.Texture2DArray.MipLevels = textureMipLevels; + viewDesc.Texture2DArray.MostDetailedMip = 0; + } + if (inputDesc.arrayLength != 0) + viewDesc.ViewDimension = (D3D11_SRV_DIMENSION)(int)(viewDesc.ViewDimension + 1); + desc.Width = textureSize; + desc.Height = textureSize; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + ID3D11Texture2D * texture; + dxDevice->CreateTexture2D(&desc, subRes.Buffer(), &texture); + dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut); + } + else if (inputDesc.dimension == 3) + { + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + D3D11_TEXTURE3D_DESC desc = { 0 }; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET | D3D11_BIND_UNORDERED_ACCESS; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS; + desc.MipLevels = textureMipLevels; + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + desc.Width = textureSize; + desc.Height = textureSize; + desc.Depth = textureSize; + desc.Usage = D3D11_USAGE_DEFAULT; + ID3D11Texture3D * texture; + dxDevice->CreateTexture3D(&desc, subRes.Buffer(), &texture); + if (inputDesc.arrayLength != 0) + viewDesc.ViewDimension = (D3D11_SRV_DIMENSION)(int)(viewDesc.ViewDimension + 1); + viewDesc.Texture3D.MipLevels = textureMipLevels; + viewDesc.Texture3D.MostDetailedMip = 0; + dxDevice->CreateShaderResourceView(texture, &viewDesc, &viewOut); + } + } + + void createInputSampler(const InputSamplerDesc & inputDesc, ID3D11SamplerState * & stateOut) + { + D3D11_SAMPLER_DESC desc; + memset(&desc, 0, sizeof(desc)); + desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + if (inputDesc.isCompareSampler) + { + desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL; + desc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; + } + else + desc.Filter = D3D11_FILTER_ANISOTROPIC; + desc.MaxAnisotropy = 16; + desc.MinLOD = 0.0f; + desc.MaxLOD = 100.0f; + dxDevice->CreateSamplerState(&desc, &stateOut); + } + virtual BindingState * createBindingState(const ShaderInputLayout & layout) + { + D3DBindingState * rs = new D3DBindingState(); + for (auto & entry : layout.entries) + { + D3DBinding rsEntry; + rsEntry.type = entry.type; + rsEntry.binding = entry.hlslBinding; + rsEntry.isOutput = entry.isOutput; + switch (entry.type) + { + case ShaderInputType::Buffer: + { + createInputBuffer(entry.bufferDesc, entry.bufferData, rsEntry.buffer, rsEntry.uav, rsEntry.srv); + rsEntry.bufferLength = entry.bufferData.Count() * sizeof(unsigned int); + } + break; + case ShaderInputType::Texture: + { + createInputTexture(entry.textureDesc, rsEntry.srv); + } + break; + case ShaderInputType::Sampler: + { + createInputSampler(entry.samplerDesc, rsEntry.samplerState); + } + break; + case ShaderInputType::CombinedTextureSampler: + { + throw "not implemented"; + } + break; + } + rs->bindings.Add(rsEntry); + } + + return (BindingState*)rs; + } + + void applyBindingState(bool isCompute) + { + auto dxContext = dxImmediateContext; + for (auto & binding : currentBindings->bindings) + { + if (binding.type == ShaderInputType::Buffer) + { + if (binding.uav) + { + if (isCompute) + dxContext->CSSetUnorderedAccessViews(binding.binding, 1, &binding.uav, nullptr); + else + dxContext->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, + nullptr, nullptr, binding.binding, 1, &binding.uav, nullptr); + } + else + { + if (isCompute) + dxContext->CSSetShaderResources(binding.binding, 1, &binding.srv); + else + { + dxContext->PSSetShaderResources(binding.binding, 1, &binding.srv); + dxContext->VSSetShaderResources(binding.binding, 1, &binding.srv); + } + } + } + else if (binding.type == ShaderInputType::Texture) + { + if (binding.uav) + { + if (isCompute) + dxContext->CSSetUnorderedAccessViews(binding.binding, 1, &binding.uav, nullptr); + else + dxContext->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, + nullptr, nullptr, binding.binding, 1, &binding.uav, nullptr); + } + else + { + if (isCompute) + dxContext->CSSetShaderResources(binding.binding, 1, &binding.srv); + else + { + dxContext->PSSetShaderResources(binding.binding, 1, &binding.srv); + dxContext->VSSetShaderResources(binding.binding, 1, &binding.srv); + } + } + } + else if (binding.type == ShaderInputType::Sampler) + { + if (isCompute) + dxContext->CSSetSamplers(binding.binding, 1, &binding.samplerState); + else + { + dxContext->PSSetSamplers(binding.binding, 1, &binding.samplerState); + dxContext->VSSetSamplers(binding.binding, 1, &binding.samplerState); + } + } + else + throw "not implemented"; + } + } + + virtual void setBindingState(BindingState * state) + { + auto dxBindingState = (D3DBindingState*) state; + currentBindings = dxBindingState; + } + + virtual void serializeOutput(BindingState* state, const char * fileName) + { + auto dxContext = dxImmediateContext; + auto dxBindingState = (D3DBindingState*)state; + FILE * f = fopen(fileName, "wt"); + for (auto & binding : dxBindingState->bindings) + { + if (binding.isOutput) + { + if (binding.buffer) + { + auto ptr = (unsigned int *)map(binding.buffer, MapFlavor::HostRead); + for (auto i = 0u; i < binding.bufferLength / sizeof(unsigned int); i++) + fprintf(f, "%X\n", ptr[i]); + unmap(binding.buffer); + } + else + { + throw "not implemented"; + } + } + } + fclose(f); + } }; diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp index 55647fb25..ff9d54eb6 100644 --- a/tools/render-test/render-gl.cpp +++ b/tools/render-test/render-gl.cpp @@ -613,6 +613,21 @@ public: { glDispatchCompute(x, y, z); } + + virtual BindingState * createBindingState(const ShaderInputLayout & layout) + { + return nullptr; + } + + virtual void setBindingState(BindingState * state) + { + + } + + virtual void serializeOutput(BindingState* state, const char * fileName) + { + + } }; diff --git a/tools/render-test/render-test.vcxproj b/tools/render-test/render-test.vcxproj index 94af429e8..0b0f6b05e 100644 --- a/tools/render-test/render-test.vcxproj +++ b/tools/render-test/render-test.vcxproj @@ -96,6 +96,8 @@ <WarningLevel>Level3</WarningLevel> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>../../source/</AdditionalIncludeDirectories> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> </ClCompile> <Link> <SubSystem>Console</SubSystem> @@ -109,6 +111,8 @@ <WarningLevel>Level3</WarningLevel> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>../../source/</AdditionalIncludeDirectories> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> </ClCompile> <Link> <SubSystem>Console</SubSystem> @@ -124,6 +128,8 @@ <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>../../source/</AdditionalIncludeDirectories> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> </ClCompile> <Link> <SubSystem>Console</SubSystem> @@ -141,6 +147,8 @@ <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>../../source/</AdditionalIncludeDirectories> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> </ClCompile> <Link> <SubSystem>Console</SubSystem> @@ -154,6 +162,7 @@ <ClCompile Include="options.cpp" /> <ClCompile Include="render-d3d11.cpp" /> <ClCompile Include="render-gl.cpp" /> + <ClCompile Include="shader-input-layout.cpp" /> <ClCompile Include="slang-support.cpp" /> </ItemGroup> <ItemGroup> @@ -161,10 +170,14 @@ <ClInclude Include="render-d3d11.h" /> <ClInclude Include="render-gl.h" /> <ClInclude Include="render.h" /> + <ClInclude Include="shader-input-layout.h" /> <ClInclude Include="slang-support.h" /> <ClInclude Include="window.h" /> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\..\source\core\core.vcxproj"> + <Project>{f9be7957-8399-899e-0c49-e714fddd4b65}</Project> + </ProjectReference> <ProjectReference Include="..\..\source\slang\slang.vcxproj"> <Project>{db00da62-0533-4afd-b59f-a67d5b3a0808}</Project> </ProjectReference> diff --git a/tools/render-test/render-test.vcxproj.filters b/tools/render-test/render-test.vcxproj.filters index 6e0ff295a..985e24b8b 100644 --- a/tools/render-test/render-test.vcxproj.filters +++ b/tools/render-test/render-test.vcxproj.filters @@ -30,6 +30,9 @@ <ClCompile Include="slang-support.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="shader-input-layout.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="options.h"> @@ -50,5 +53,8 @@ <ClInclude Include="slang-support.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="shader-input-layout.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> </Project>
\ No newline at end of file diff --git a/tools/render-test/render.h b/tools/render-test/render.h index 7f8f2fffa..706868e9a 100644 --- a/tools/render-test/render.h +++ b/tools/render-test/render.h @@ -3,13 +3,14 @@ #include "options.h" #include "window.h" +#include "shader-input-layout.h" namespace renderer_test { typedef struct Buffer Buffer; typedef struct InputLayout InputLayout; typedef struct ShaderProgram ShaderProgram; - +typedef struct BindingState BindingState; struct ShaderCompileRequest { struct SourceInfo @@ -89,11 +90,11 @@ public: virtual void presentFrame() = 0; virtual void captureScreenShot(char const* outputPath) = 0; - + virtual void serializeOutput(BindingState * state, char const* outputPath) = 0; virtual Buffer* createBuffer(BufferDesc const& desc) = 0; virtual InputLayout* createInputLayout(InputElementDesc const* inputElements, UInt inputElementCount) = 0; - + virtual BindingState* createBindingState(const ShaderInputLayout & shaderInput) = 0; virtual ShaderCompiler* getShaderCompiler() = 0; virtual void* map(Buffer* buffer, MapFlavor flavor) = 0; @@ -101,7 +102,7 @@ public: virtual void setInputLayout(InputLayout* inputLayout) = 0; virtual void setPrimitiveTopology(PrimitiveTopology topology) = 0; - + virtual void setBindingState(BindingState * state) = 0; virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer* const* buffers, UInt const* strides, UInt const* offsets) = 0; inline void setVertexBuffer(UInt slot, Buffer* buffer, UInt stride, UInt offset = 0) diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp new file mode 100644 index 000000000..b606a1a13 --- /dev/null +++ b/tools/render-test/shader-input-layout.cpp @@ -0,0 +1,221 @@ +#include "shader-input-layout.h" +#include "core/token-reader.h" + +namespace renderer_test +{ + using namespace Slang; + void ShaderInputLayout::Parse(const char * source) + { + entries.Clear(); + auto lines = Split(source, '\n'); + for (auto & line : lines) + { + if (line.StartsWith("//TEST_INPUT:")) + { + auto lineContent = line.SubString(13, line.Length() - 13); + TokenReader parser(lineContent); + try + { + ShaderInputLayoutEntry entry; + + if (parser.LookAhead("cbuffer")) + { + entry.type = ShaderInputType::Buffer; + entry.bufferDesc.type = InputBufferType::ConstantBuffer; + } + else if (parser.LookAhead("ubuffer")) + { + entry.type = ShaderInputType::Buffer; + entry.bufferDesc.type = InputBufferType::StorageBuffer; + } + else if (parser.LookAhead("Texture1D")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 1; + } + else if (parser.LookAhead("Texture2D")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 2; + } + else if (parser.LookAhead("Texture3D")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 3; + } + else if (parser.LookAhead("TextureCube")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 2; + entry.textureDesc.isCube = true; + } + else if (parser.LookAhead("RWTexture1D")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 1; + entry.textureDesc.isRWTexture = true; + } + else if (parser.LookAhead("RWTexture2D")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 2; + entry.textureDesc.isRWTexture = true; + } + else if (parser.LookAhead("RWTexture3D")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 3; + entry.textureDesc.isRWTexture = true; + } + else if (parser.LookAhead("RWTextureCube")) + { + entry.type = ShaderInputType::Texture; + entry.textureDesc.dimension = 2; + entry.textureDesc.isCube = true; + entry.textureDesc.isRWTexture = true; + } + else if (parser.LookAhead("Sampler")) + { + entry.type = ShaderInputType::Sampler; + } + else if (parser.LookAhead("Sampler1D")) + { + entry.type = ShaderInputType::CombinedTextureSampler; + entry.textureDesc.dimension = 1; + } + else if (parser.LookAhead("Sampler2D")) + { + entry.type = ShaderInputType::CombinedTextureSampler; + entry.textureDesc.dimension = 2; + } + else if (parser.LookAhead("Sampler3D")) + { + entry.type = ShaderInputType::CombinedTextureSampler; + entry.textureDesc.dimension = 3; + } + else if (parser.LookAhead("SamplerCube")) + { + entry.type = ShaderInputType::CombinedTextureSampler; + entry.textureDesc.dimension = 2; + entry.textureDesc.isCube = true; + } + else if (parser.LookAhead("render_targets")) + { + numRenderTargets = parser.ReadInt(); + continue; + } + parser.ReadToken(); + // parse options + if (parser.LookAhead("(")) + { + parser.Read("("); + while (!parser.IsEnd() && !parser.LookAhead(")")) + { + auto word = parser.ReadWord(); + if (word == "depth") + { + entry.textureDesc.isDepthTexture = true; + } + else if (word == "depthCompare") + { + entry.samplerDesc.isCompareSampler = true; + } + else if (word == "arrayLength") + { + parser.Read("="); + entry.textureDesc.arrayLength = parser.ReadInt(); + } + else if (word == "stride") + { + parser.Read("="); + entry.bufferDesc.stride = parser.ReadInt(); + } + else if (word == "size") + { + parser.Read("="); + entry.textureDesc.size = parser.ReadInt(); + } + else if (word == "data") + { + parser.Read("="); + parser.Read("["); + while (!parser.IsEnd() && !parser.LookAhead("]")) + { + if (parser.NextToken().Type == TokenType::IntLiteral) + { + entry.bufferData.Add(parser.ReadUInt()); + } + else + { + auto floatNum = parser.ReadFloat(); + entry.bufferData.Add(*(unsigned int*)&floatNum); + } + } + parser.Read("]"); + } + else if (word == "content") + { + parser.Read("="); + auto contentWord = parser.ReadWord(); + if (contentWord == "zero") + entry.textureDesc.content = InputTextureContent::Zero; + else if (contentWord == "one") + entry.textureDesc.content = InputTextureContent::One; + else if (contentWord == "chessboard") + entry.textureDesc.content = InputTextureContent::ChessBoard; + else + entry.textureDesc.content = InputTextureContent::Gradient; + } + if (parser.LookAhead(",")) + parser.Read(","); + else + break; + } + } + parser.Read(")"); + // parse bindings + if (parser.LookAhead(":")) + { + parser.Read(":"); + while (!parser.IsEnd()) + { + if (parser.LookAhead("dxbinding")) + { + parser.ReadToken(); + parser.Read("("); + entry.hlslBinding = parser.ReadInt(); + parser.Read(")"); + } + else if (parser.LookAhead("glbinding")) + { + parser.ReadToken(); + parser.Read("("); + entry.glslBinding = entry.glslLocation = parser.ReadInt(); + if (parser.LookAhead(",")) + { + parser.Read(","); + entry.glslLocation = parser.ReadInt(); + } + parser.Read(")"); + } + else if (parser.LookAhead("out")) + { + parser.ReadToken(); + entry.isOutput = true; + } + if (parser.LookAhead(",")) + parser.Read(","); + } + } + entries.Add(entry); + } + catch (TextFormatException) + { + throw TextFormatException("Invalid input syntax at line " + parser.NextToken().Position.Line); + } + } + } + + + } +}
\ No newline at end of file diff --git a/tools/render-test/shader-input-layout.h b/tools/render-test/shader-input-layout.h new file mode 100644 index 000000000..f2258b7b9 --- /dev/null +++ b/tools/render-test/shader-input-layout.h @@ -0,0 +1,61 @@ +#ifndef SLANG_TEST_SHADER_INPUT_LAYOUT_H +#define SLANG_TEST_SHADER_INPUT_LAYOUT_H + +#include "core/basic.h" + +namespace renderer_test +{ + enum class ShaderInputType + { + Buffer, Texture, Sampler, CombinedTextureSampler + }; + enum class InputTextureContent + { + Zero, One, ChessBoard, Gradient + }; + struct InputTextureDesc + { + int dimension = 2; + int arrayLength = 0; + bool isCube = false; + bool isDepthTexture = false; + bool isRWTexture = false; + int size = 4; + InputTextureContent content = InputTextureContent::One; + }; + enum class InputBufferType + { + ConstantBuffer, StorageBuffer + }; + struct InputBufferDesc + { + InputBufferType type = InputBufferType::ConstantBuffer; + int stride = 0; // stride == 0 indicates an unstructured buffer. + }; + struct InputSamplerDesc + { + bool isCompareSampler = false; + }; + class ShaderInputLayoutEntry + { + public: + ShaderInputType type; + Slang::List<unsigned int> bufferData; + InputTextureDesc textureDesc; + InputBufferDesc bufferDesc; + InputSamplerDesc samplerDesc; + bool isOutput = false; + int hlslBinding = -1; + int glslBinding = -1; + int glslLocation = -1; + }; + class ShaderInputLayout + { + public: + Slang::List<ShaderInputLayoutEntry> entries; + int numRenderTargets = 1; + void Parse(const char * source); + }; +} + +#endif
\ No newline at end of file |
