//-------------------------------------------------------------------------------------- // // GenerateShadowMap // // Renders the hair from the point of view of the light into a shadow map // //-------------------------------------------------------------------------------------- void TressFXRenderer::GenerateShadowMap(ID3D11DeviceContext* pd3dContext, float density, float screenWidth, float screenHeight) { // Get original render target and depth stencil view ID3D11RenderTargetView* pRTV = NULL; ID3D11DepthStencilView* pDSV = NULL; pd3dContext->OMGetRenderTargets( 1, &pRTV, &pDSV ); D3D11_VIEWPORT viewportSMHair = {0, 0, SM_HAIR_WIDTH, SM_HAIR_HEIGHT, 0.0f, 1.0f}; pd3dContext->RSSetViewports( 1, &viewportSMHair ); // clear depth for early z pd3dContext->ClearDepthStencilView(m_pSMHairDSV, D3D11_CLEAR_DEPTH|D3D10_CLEAR_STENCIL, 1.0, 0); // set render target to shadow map texture pd3dContext->OMSetRenderTargets(0, 0, m_pSMHairDSV); RenderHairGeometry(pd3dContext, m_pVSGenerateHairSM, NULL, density); // reset view port D3D11_VIEWPORT viewportWin = {0, 0, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f}; pd3dContext->RSSetViewports(1, &viewportWin); // reset render targets pd3dContext->OMSetRenderTargets(1, &pRTV, pDSV); AMD_SAFE_RELEASE( pRTV ); AMD_SAFE_RELEASE( pDSV ); // set the hair shadow map shader resource view pd3dContext->PSSetShaderResources(IDSRV_HAIRSM, 1, &m_pSMHairSRV); }
HRESULT Mesh::Release() { if (m_isSdkMesh) { m_sdkMesh.Destroy(); return S_OK; } #ifdef AMD_SDK_MINIMAL else { // the minimal-dependencies version of AMD_SDK // only supports sdkmesh return E_FAIL; } #else AMD_SAFE_RELEASE(_b1d_vertex); AMD_SAFE_RELEASE(_b1d_index); for (unsigned int i = 0; i < _t2d.size(); i++) { AMD_SAFE_RELEASE(_t2d[i]); AMD_SAFE_RELEASE(_srv[i]); } _t2d.clear(); _srv.clear(); return S_OK; #endif }
void Buffer::Release() { AMD_SAFE_RELEASE(_b1d); AMD_SAFE_RELEASE(_srv); AMD_SAFE_RELEASE(_uav); AMD_SAFE_RELEASE(_staging_counter_b1d); AMD_SAFE_RELEASE(_staging_b1d); }
void TressFXShortCut::DestroyScreenSizedItems() { AMD_SAFE_RELEASE(m_pAccumInvAlpha_SRV); AMD_SAFE_RELEASE(m_pAccumInvAlpha_RTV); AMD_SAFE_RELEASE(m_pAccumInvAlpha); AMD_SAFE_RELEASE(m_pFragmentDepthsTexture_SRV); AMD_SAFE_RELEASE(m_pFragmentDepthsTexture_UAV); AMD_SAFE_RELEASE(m_pFragmentDepthsTexture); AMD_SAFE_RELEASE(m_pFragmentColorsTexture_RTV); AMD_SAFE_RELEASE(m_pFragmentColorsTexture_SRV); AMD_SAFE_RELEASE(m_pFragmentColorsTexture); m_FragmentColors.Destroy(); }
//-------------------------------------------------------------------------------------- // // DeletePPLL // // Deletes the PPLL buffers when the refCount goes to 0 // //-------------------------------------------------------------------------------------- void TressFXRenderer::DeletePPLL() { if (g_PPLBuffers.refCount == 0) { return; } g_PPLBuffers.refCount--; m_pHeadPPLL_Buffer = NULL; m_pHeadPPLL_SRV = NULL; m_pHeadPPLL_UAV = NULL; m_pPPLL_Buffer = NULL; m_pPPLL_UAV = NULL; m_pPPLL_SRV = NULL; if (g_PPLBuffers.refCount == 0) { AMD_SAFE_RELEASE(g_PPLBuffers.pHeadPPLL_Buffer); AMD_SAFE_RELEASE(g_PPLBuffers.pHeadPPLL_SRV); AMD_SAFE_RELEASE(g_PPLBuffers.pHeadPPLL_UAV); AMD_SAFE_RELEASE(g_PPLBuffers.pPPLL_Buffer); AMD_SAFE_RELEASE(g_PPLBuffers.pPPLL_UAV); AMD_SAFE_RELEASE(g_PPLBuffers.pPPLL_SRV); g_PPLBuffers.width = 0; g_PPLBuffers.height = 0; } }
HRESULT Buffer::CreateBuffer(ID3D11Device * device, unsigned int uSizeInBytes, unsigned int uSizeOfStructure, unsigned int uCPUAccess, unsigned int uBindFlags, D3D11_USAGE usage, DXGI_FORMAT SRV_Format, DXGI_FORMAT UAV_Format, unsigned int uUAVFlags, unsigned int uB1DFlags, void * data) { HRESULT hr = S_OK; if (NULL == _b1d) { D3D11_SUBRESOURCE_DATA subresource_data; memset(&subresource_data, 0, sizeof(subresource_data)); subresource_data.pSysMem = data; D3D11_BUFFER_DESC b1d_desc; memset(&b1d_desc, 0, sizeof(b1d_desc)); b1d_desc.BindFlags = uBindFlags; b1d_desc.ByteWidth = uSizeInBytes; b1d_desc.CPUAccessFlags = uCPUAccess; b1d_desc.Usage = usage; b1d_desc.StructureByteStride = (uB1DFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) ? uSizeOfStructure : 0; b1d_desc.MiscFlags = uB1DFlags; hr = device->CreateBuffer(&b1d_desc, data ? &subresource_data : NULL, &_b1d); assert(S_OK == hr); b1d_desc.BindFlags = 0; b1d_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; b1d_desc.Usage = D3D11_USAGE_STAGING; b1d_desc.MiscFlags = 0; hr = device->CreateBuffer(&b1d_desc, NULL, &_staging_b1d); assert(S_OK == hr); _size_in_bytes = uSizeInBytes; D3D11_BUFFER_DESC staging_desc; memset(&staging_desc, 0, sizeof(staging_desc)); staging_desc.ByteWidth = sizeof(unsigned int); staging_desc.Usage = D3D11_USAGE_STAGING; staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; hr = device->CreateBuffer(&staging_desc, NULL, &_staging_counter_b1d); assert(S_OK == hr); } if (uBindFlags & D3D11_BIND_SHADER_RESOURCE) { AMD_SAFE_RELEASE(_srv); D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; memset(&srv_desc, 0, sizeof(srv_desc)); srv_desc.Format = SRV_Format; srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; srv_desc.Buffer.FirstElement = 0; srv_desc.Buffer.NumElements = uSizeInBytes / uSizeOfStructure; hr = device->CreateShaderResourceView(_b1d, &srv_desc, &_srv); assert(S_OK == hr); } if (uBindFlags & D3D11_BIND_UNORDERED_ACCESS) { AMD_SAFE_RELEASE(_uav); D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; memset(&uav_desc, 0, sizeof(D3D11_UNORDERED_ACCESS_VIEW_DESC)); uav_desc.Format = UAV_Format; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; uav_desc.Buffer.FirstElement = 0; uav_desc.Buffer.NumElements = uSizeInBytes / uSizeOfStructure; uav_desc.Buffer.Flags = uUAVFlags; hr = device->CreateUnorderedAccessView(_b1d, &uav_desc, &_uav); assert(S_OK == hr); } return hr; }
HRESULT Mesh::Create(ID3D11Device * pDevice, const char * path, const char * name, bool sdkmesh) { m_isSdkMesh = sdkmesh; if (sdkmesh) { char filename[256]; sprintf(filename, "%s%s", path, name); std::string fname(filename); std::wstring wfname(fname.begin(), fname.end()); return m_sdkMesh.Create(pDevice, wfname.c_str(), false); } #ifdef AMD_SDK_MINIMAL else { // the minimal-dependencies version of AMD_SDK // only supports sdkmesh return E_FAIL; } #else HRESULT hr = S_OK; Assimp::Importer importer; int num_vertices = 0; int num_faces = 0; std::string filename = std::string(path) + std::string(name); aiScene* scene = (aiScene*)importer.ReadFile(filename.c_str(), 0); if (!scene) { return E_FAIL; } _id = crcFast((const unsigned char *)filename.c_str(), (int)filename.length()); if (scene->HasMeshes() && scene->mNumMeshes > 0) { for (int i = 0; i < (int)scene->mNumMeshes; i++) { num_vertices += scene->mMeshes[i]->mNumVertices; num_faces += scene->mMeshes[i]->mNumFaces; } if (num_vertices == 0 || num_faces == 0) { return S_OK; } int current_vertex = 0; int current_face = 0; _material_group.resize(scene->mNumMeshes); _vertex.resize(num_vertices); _index.resize(num_faces * 3); ID3D11DeviceContext * pContext = NULL; pDevice->GetImmediateContext(&pContext); for (unsigned int i = 0; i < scene->mNumMeshes; i++) { ID3D11Texture2D * t2d = NULL; ID3D11ShaderResourceView * srv = NULL; aiMesh * mesh = scene->mMeshes[i]; aiMaterial * material = scene->mMaterials[mesh->mMaterialIndex]; aiString c_texture_filename; material->Get(AI_MATKEY_TEXTURE_DIFFUSE(0), c_texture_filename); std::string tex_filename = std::string(path) + std::string(c_texture_filename.C_Str()); { WCHAR wc_texture_filename[1024]; mbstowcs(wc_texture_filename, tex_filename.c_str(), tex_filename.length() + 1); unsigned int bind_flags = D3D11_BIND_SHADER_RESOURCE; hr = DirectX::CreateDDSTextureFromFileEx(pDevice, wc_texture_filename, 0, D3D11_USAGE_DEFAULT, bind_flags, 0, 0, true, (ID3D11Resource**)&t2d, &srv); } _material_group[i]._texture_index = (int)_t2d.size(); _t2d.push_back(t2d); _srv.push_back(srv); _material_group[i]._first_index = current_face; _material_group[i]._index_count = mesh->mNumFaces * 3; aiVector3D * position = mesh->HasPositions() ? mesh->mVertices : NULL; aiVector3D * normal = mesh->HasNormals() ? mesh->mNormals : NULL; aiVector3D * uv = mesh->HasTextureCoords(0) ? mesh->mTextureCoords[0] : NULL; for (unsigned int j = 0; j < mesh->mNumVertices; j++) { if (position != NULL) { memcpy( &_vertex[current_vertex + j].position, &position[j], sizeof( float ) * 3 ); } if (normal != NULL) { memcpy( &_vertex[current_vertex + j].normal, &normal[j], sizeof( float ) * 3 ); } if (uv != NULL) { memcpy( &_vertex[current_vertex + j].uv, &uv[j], sizeof( float ) * 2 ); } } if (mesh->HasFaces()) { aiFace * f = mesh->mFaces; for (unsigned int j = 0; j < mesh->mNumFaces; j++) { _index[current_face + j * 3 + 0] = current_vertex + f[j].mIndices[0]; _index[current_face + j * 3 + 1] = current_vertex + f[j].mIndices[1]; _index[current_face + j * 3 + 2] = current_vertex + f[j].mIndices[2]; } } current_face += mesh->mNumFaces * 3; current_vertex += mesh->mNumVertices; } AMD_SAFE_RELEASE(pContext); CD3D11_BUFFER_DESC vertexDesc, indexDesc; vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_SHADER_RESOURCE; vertexDesc.ByteWidth = sizeof(Vertex) * num_vertices; vertexDesc.CPUAccessFlags = 0; vertexDesc.MiscFlags = 0; vertexDesc.StructureByteStride = 0; vertexDesc.Usage = D3D11_USAGE_IMMUTABLE; indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexDesc.ByteWidth = sizeof(int) * num_faces * 3; indexDesc.CPUAccessFlags = 0; indexDesc.MiscFlags = 0; indexDesc.StructureByteStride = 0; indexDesc.Usage = D3D11_USAGE_IMMUTABLE; D3D11_SUBRESOURCE_DATA vertexData, indexData; memset(&vertexData, 0, sizeof(vertexData)); memset(&indexData, 0, sizeof(indexData)); vertexData.pSysMem = &_vertex[0]; indexData.pSysMem = &_index[0]; hr = pDevice->CreateBuffer(&vertexDesc, &vertexData, &_b1d_vertex); hr = pDevice->CreateBuffer(&indexDesc, &indexData, &_b1d_index); } return hr; #endif }
AMD_AOFX_DLL_API AOFX_RETURN_CODE AOFX_DebugSerialize(AOFX_Desc& desc, const char* params) { AMD_OUTPUT_DEBUG_STRING("CALL: " AMD_FUNCTION_NAME " \n"); HRESULT hr = S_OK; ID3D11Texture2D *pDepthT2D = NULL, *pNormalT2D = NULL; std::string strParams(params); std::wstring wstrParams(strParams.begin(), strParams.end()); if (desc.m_pDepthSRV) { std::wstring depth = wstrParams + L".depth.dds"; desc.m_pDepthSRV->GetResource((ID3D11Resource**)&pDepthT2D); hr = DirectX::SaveDDSTextureToFile(desc.m_pDeviceContext, pDepthT2D, depth.c_str()); AMD_SAFE_RELEASE(pDepthT2D); if (hr != S_OK) { AMD_OUTPUT_DEBUG_STRING("AMD_AO DebugSerialize Error : Can't save Depth Texture\n"); return AOFX_RETURN_CODE_FAIL; } } if (desc.m_pNormalSRV) { std::wstring normal = wstrParams + L".normal.dds"; desc.m_pNormalSRV->GetResource((ID3D11Resource**)&pNormalT2D); hr = DirectX::SaveDDSTextureToFile(desc.m_pDeviceContext, pNormalT2D, normal.c_str()); AMD_SAFE_RELEASE(pNormalT2D); if (hr != S_OK) { AMD_OUTPUT_DEBUG_STRING("AMD_AO DebugSerialize Error : Can't save Normal Texture\n"); return AOFX_RETURN_CODE_FAIL; } } strParams += ".txt"; FILE * file = fopen(strParams.c_str(), "wt"); if (file != NULL) { serialize_uint(file, "desc.m_MultiResLayerCount", (uint *)&desc.m_MultiResLayerCount); for (uint i = 0; i < desc.m_MultiResLayerCount; i++) { serialize_uint(file, "desc.m_LayerProcess", (uint *)&desc.m_LayerProcess[i]); serialize_uint(file, "desc.m_BilateralBlurRadius", (uint *)&desc.m_BilateralBlurRadius[i]); serialize_uint(file, "desc.m_SampleCount", (uint *)&desc.m_SampleCount[i]); serialize_uint(file, "desc.m_NormalOption", (uint *)&desc.m_NormalOption[i]); serialize_uint(file, "desc.m_TapType", (uint *)&desc.m_TapType[i]); serialize_float(file, "desc.m_MultiResLayerScale", (float *)&desc.m_MultiResLayerScale[i]); serialize_float(file, "desc.m_PowIntensity", (float *)&desc.m_PowIntensity[i]); serialize_float(file, "desc.m_RejectRadius", (float *)&desc.m_RejectRadius[i]); serialize_float(file, "desc.m_AcceptRadius", (float *)&desc.m_AcceptRadius[i]); serialize_float(file, "desc.m_RecipFadeOutDist", (float *)&desc.m_RecipFadeOutDist[i]); serialize_float(file, "desc.m_LinearIntensity", (float *)&desc.m_LinearIntensity[i]); serialize_float(file, "desc.m_NormalScale", (float *)&desc.m_NormalScale[i]); serialize_float(file, "desc.m_ViewDistanceDiscard", (float *)&desc.m_ViewDistanceDiscard[i]); serialize_float(file, "desc.m_ViewDistanceFade", (float *)&desc.m_ViewDistanceFade[i]); serialize_float(file, "desc.m_DepthUpsampleThreshold", (float *)&desc.m_DepthUpsampleThreshold[i]); } serialize_uint(file, "desc.m_Implementation", (uint *)&desc.m_Implementation); serialize_float4(file, "desc.m_Camera.m_View.r[0]", (float *)&desc.m_Camera.m_View.r[0]); serialize_float4(file, "desc.m_Camera.m_View.r[1]", (float *)&desc.m_Camera.m_View.r[1]); serialize_float4(file, "desc.m_Camera.m_View.r[2]", (float *)&desc.m_Camera.m_View.r[2]); serialize_float4(file, "desc.m_Camera.m_View.r[3]", (float *)&desc.m_Camera.m_View.r[3]); serialize_float4(file, "desc.m_Camera.m_Projection.r[0]", (float *)&desc.m_Camera.m_Projection.r[0]); serialize_float4(file, "desc.m_Camera.m_Projection.r[1]", (float *)&desc.m_Camera.m_Projection.r[1]); serialize_float4(file, "desc.m_Camera.m_Projection.r[2]", (float *)&desc.m_Camera.m_Projection.r[2]); serialize_float4(file, "desc.m_Camera.m_Projection.r[3]", (float *)&desc.m_Camera.m_Projection.r[3]); serialize_float4(file, "desc.m_Camera.m_ViewProjection.r[0]", (float *)&desc.m_Camera.m_ViewProjection.r[0]); serialize_float4(file, "desc.m_Camera.m_ViewProjection.r[1]", (float *)&desc.m_Camera.m_ViewProjection.r[1]); serialize_float4(file, "desc.m_Camera.m_ViewProjection.r[2]", (float *)&desc.m_Camera.m_ViewProjection.r[2]); serialize_float4(file, "desc.m_Camera.m_ViewProjection.r[3]", (float *)&desc.m_Camera.m_ViewProjection.r[3]); serialize_float4(file, "desc.m_Camera.m_View_Inv.r[0]", (float *)&desc.m_Camera.m_View_Inv.r[0]); serialize_float4(file, "desc.m_Camera.m_View_Inv.r[1]", (float *)&desc.m_Camera.m_View_Inv.r[1]); serialize_float4(file, "desc.m_Camera.m_View_Inv.r[2]", (float *)&desc.m_Camera.m_View_Inv.r[2]); serialize_float4(file, "desc.m_Camera.m_View_Inv.r[3]", (float *)&desc.m_Camera.m_View_Inv.r[3]); serialize_float4(file, "desc.m_Camera.m_Projection_Inv.r[0]", (float *)&desc.m_Camera.m_Projection_Inv.r[0]); serialize_float4(file, "desc.m_Camera.m_Projection_Inv.r[1]", (float *)&desc.m_Camera.m_Projection_Inv.r[1]); serialize_float4(file, "desc.m_Camera.m_Projection_Inv.r[2]", (float *)&desc.m_Camera.m_Projection_Inv.r[2]); serialize_float4(file, "desc.m_Camera.m_Projection_Inv.r[3]", (float *)&desc.m_Camera.m_Projection_Inv.r[3]); serialize_float4(file, "desc.m_Camera.m_ViewProjection_Inv.r[0]", (float *)&desc.m_Camera.m_ViewProjection_Inv.r[0]); serialize_float4(file, "desc.m_Camera.m_ViewProjection_Inv.r[1]", (float *)&desc.m_Camera.m_ViewProjection_Inv.r[1]); serialize_float4(file, "desc.m_Camera.m_ViewProjection_Inv.r[2]", (float *)&desc.m_Camera.m_ViewProjection_Inv.r[2]); serialize_float4(file, "desc.m_Camera.m_ViewProjection_Inv.r[3]", (float *)&desc.m_Camera.m_ViewProjection_Inv.r[3]); serialize_float3(file, "desc.m_Camera.m_Position", (float *)&desc.m_Camera.m_Position); serialize_float3(file, "desc.m_Camera.m_Direction", (float *)&desc.m_Camera.m_Direction); serialize_float3(file, "desc.m_Camera.m_Right", (float *)&desc.m_Camera.m_Right); serialize_float3(file, "desc.m_Camera.m_Up", (float *)&desc.m_Camera.m_Up); serialize_float(file, "desc.m_Camera.m_Aspect", (float *)&desc.m_Camera.m_Aspect); serialize_float(file, "desc.m_Camera.m_FarPlane", (float *)&desc.m_Camera.m_FarPlane); serialize_float(file, "desc.m_Camera.m_NearPlane", (float *)&desc.m_Camera.m_NearPlane); serialize_float(file, "desc.m_Camera.m_Fov", (float *)&desc.m_Camera.m_Fov); serialize_float4(file, "desc.m_Camera.m_Color", (float *)&desc.m_Camera.m_Color); serialize_uint2(file, "desc.m_InputSize", (uint*)&desc.m_InputSize); serialize_uint(file, "desc.m_OutputChannelsFlag", (uint *)&desc.m_OutputChannelsFlag); fclose(file); } else { AMD_OUTPUT_DEBUG_STRING("AMD_AO DebugSerialize Error : Can't save AO Parameters\n"); } return AOFX_RETURN_CODE_SUCCESS; }
void TressFXRenderer::RenderHairShortcut(ID3D11DeviceContext* pd3dContext) { // Get original render target and depth stencil view ID3D11RenderTargetView* pRTV = NULL; ID3D11DepthStencilView* pDSV = NULL; pd3dContext->OMGetRenderTargets(1, &pRTV, &pDSV); ID3D11PixelShader* pPS = m_ShortCut.SetupDepthPass(pd3dContext, pRTV, pDSV); // DEPTH FILL if (m_hairParams.bAntialias) { if (m_hairParams.strandCopies > 1) { RenderHairGeometry(pd3dContext, m_pVSRenderHairAAStrandCopies, pPS, m_hairParams.density, false, m_hairParams.strandCopies); } else { RenderHairGeometry(pd3dContext, m_pVSRenderHairAA, pPS, m_hairParams.density, false, 1); } } else { if (m_hairParams.strandCopies > 1) { RenderHairGeometry(pd3dContext, m_pVSRenderHairStrandCopies, pPS, m_hairParams.density, false, m_hairParams.strandCopies); } else { RenderHairGeometry(pd3dContext, m_pVSRenderHair, pPS, m_hairParams.density, false, 1); } } // DEPTH RESOLVE pPS = m_ShortCut.SetupResolveDepth(pd3dContext, pRTV, pDSV); RenderScreenQuad(pd3dContext, m_pVSScreenQuad, pPS); // COLOR FILL pPS = m_ShortCut.SetupShadePass(pd3dContext, pRTV, pDSV); if (m_hairParams.bAntialias) { if (m_hairParams.strandCopies > 1) { RenderHairGeometry(pd3dContext, m_pVSRenderHairAAStrandCopies, pPS, m_hairParams.density, false, m_hairParams.strandCopies); } else { RenderHairGeometry(pd3dContext, m_pVSRenderHairAA, pPS, m_hairParams.density, false, 1); } } else { if (m_hairParams.strandCopies > 1) { RenderHairGeometry(pd3dContext, m_pVSRenderHairStrandCopies, pPS, m_hairParams.density, false, m_hairParams.strandCopies); } else { RenderHairGeometry(pd3dContext, m_pVSRenderHair, pPS, m_hairParams.density, false, 1); } } // COLOR RESOLVE pPS = m_ShortCut.SetupResolveColor(pd3dContext, pRTV, pDSV); RenderScreenQuad(pd3dContext, m_pVSScreenQuad, pPS); m_ShortCut.PostResolveColor(pd3dContext); pd3dContext->OMSetDepthStencilState(m_pDepthTestEnabledDSS, 0x00); pd3dContext->OMSetRenderTargets(1, &pRTV, pDSV); pd3dContext->OMSetBlendState(NULL, 0, 0xffffffff); AMD_SAFE_RELEASE(pRTV); AMD_SAFE_RELEASE(pDSV); }
//-------------------------------------------------------------------------------------- // // RenderHair // // Renders the hair in two passes. The first pass fills an A-buffer by rendering the // hair geometry into a per-pixel linked list which keeps all of the overlapping fragments. // The second pass renders a full screen quad (using a stencil mask set in the first pass // to avoid unnecessary pixels) which reads fragments from the per-pixel linked list // and blends the nearest k fragments (K-buffer) in back to front order. // //-------------------------------------------------------------------------------------- void TressFXRenderer::RenderHair(ID3D11DeviceContext* pd3dContext) { // Get original render target and depth stencil view ID3D11RenderTargetView* pRTV = NULL; ID3D11DepthStencilView* pDSV = NULL; pd3dContext->OMGetRenderTargets( 1, &pRTV, &pDSV ); // render hair const UINT dwClearDataMinusOne[1] = {0xFFFFFFFF}; pd3dContext->ClearUnorderedAccessViewUint(m_pHeadPPLL_UAV, dwClearDataMinusOne); // Clear stencil buffer to mask the rendering area // Keep depth buffer for correct depth and early z pd3dContext->ClearDepthStencilView(pDSV, D3D10_CLEAR_STENCIL, 1.0, 0); ID3D11UnorderedAccessView* pUAV[] = {m_pHeadPPLL_UAV, m_pPPLL_UAV, NULL, NULL, NULL, NULL, NULL}; UINT pUAVCounters[] = { 0, 0, 0, 0, 0, 0, 0 }; pd3dContext->OMSetRenderTargetsAndUnorderedAccessViews(1, &pRTV, pDSV, 1, 7, pUAV, pUAVCounters); // disable color write if there is no need for fragments counting pd3dContext->OMSetBlendState(m_pColorWritesOff, 0, 0xffffffff); // Enable depth test to use early z, disable depth write to make sure required layers won't be clipped out in early z pd3dContext->OMSetDepthStencilState(m_pDepthTestEnabledNoDepthWritesStencilWriteIncrementDSS, 0x00); // Pass 1: A-Buffer pass if (m_hairParams.bAntialias) { if (m_hairParams.strandCopies > 1) { RenderHairGeometry(pd3dContext, m_pVSRenderHairAAStrandCopies, m_pPSABuffer_Hair, m_hairParams.density, false, m_hairParams.strandCopies); } else { RenderHairGeometry(pd3dContext, m_pVSRenderHairAA, m_pPSABuffer_Hair, m_hairParams.density, false, 1); } } else { if (m_hairParams.strandCopies > 1) { RenderHairGeometry(pd3dContext, m_pVSRenderHairStrandCopies, m_pPSABuffer_Hair, m_hairParams.density, false, m_hairParams.strandCopies); } else { RenderHairGeometry(pd3dContext, m_pVSRenderHair, m_pPSABuffer_Hair, m_hairParams.density, false, 1); } } // Pass 2: K-Buffer pass pd3dContext->OMSetBlendState(m_pBlendStateBlendToBg, 0, 0xffffffff); pd3dContext->OMSetDepthStencilState(m_pDepthTestDisabledStencilTestLessDSS, 0x00); pUAV[0] = pUAV[1] = pUAV[2] = pUAV[3] = pUAV[4] = pUAV[5] = pUAV[6] = 0; pd3dContext->OMSetRenderTargetsAndUnorderedAccessViews(1, &pRTV, pDSV, 1, 7, pUAV, pUAVCounters); pd3dContext->PSSetShaderResources(IDSRV_HEAD_PPLL, 1, &m_pHeadPPLL_SRV); pd3dContext->PSSetShaderResources(IDSRV_PPLL, 1, &m_pPPLL_SRV); RenderScreenQuad(pd3dContext, m_pVSScreenQuad, m_pPSKBuffer_Hair); ID3D11ShaderResourceView* pNULL = NULL; pd3dContext->PSSetShaderResources(IDSRV_HEAD_PPLL, 1, &pNULL); pd3dContext->PSSetShaderResources(IDSRV_PPLL, 1, &pNULL); pd3dContext->OMSetDepthStencilState(m_pDepthTestEnabledDSS, 0x00); pd3dContext->OMSetRenderTargets(1, &pRTV, pDSV); pd3dContext->OMSetBlendState(NULL, 0, 0xffffffff); AMD_SAFE_RELEASE( pRTV ); AMD_SAFE_RELEASE( pDSV ); }
//-------------------------------------------------------------------------------------- // // CreatePPLL // // Creates the per pixel linked list buffers and views. To save space, the PPLL is // shared between multiple TressFXRenderer objects. The ref count gets incremented // when the PPLL is shared with a new TressFXRenderer object. // //-------------------------------------------------------------------------------------- HRESULT TressFXRenderer::CreatePPLL(ID3D11Device* pd3dDevice, int winWidth, int winHeight, bool resize) { HRESULT hr; // see if the buffer needs to be resized or if refCount is 0 if ((winWidth != g_PPLBuffers.width) || (winHeight != g_PPLBuffers.height) || (g_PPLBuffers.refCount == 0)) { // Release any previously allocated buffers AMD_SAFE_RELEASE(g_PPLBuffers.pHeadPPLL_Buffer); AMD_SAFE_RELEASE(g_PPLBuffers.pHeadPPLL_SRV); AMD_SAFE_RELEASE(g_PPLBuffers.pHeadPPLL_UAV); AMD_SAFE_RELEASE(g_PPLBuffers.pPPLL_Buffer); AMD_SAFE_RELEASE(g_PPLBuffers.pPPLL_UAV); AMD_SAFE_RELEASE(g_PPLBuffers.pPPLL_SRV); // linked list head texture D3D11_TEXTURE2D_DESC texDesc; texDesc.Width = winWidth; texDesc.Height = winHeight; texDesc.MipLevels = 1; texDesc.ArraySize = 1; texDesc.Format = DXGI_FORMAT_R32_UINT; texDesc.Usage = D3D11_USAGE_DEFAULT; texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; texDesc.MiscFlags = 0; texDesc.CPUAccessFlags = 0; texDesc.SampleDesc.Count=1; texDesc.SampleDesc.Quality=0; AMD_V_RETURN(pd3dDevice->CreateTexture2D(&texDesc, NULL, &g_PPLBuffers.pHeadPPLL_Buffer)); // SRV for linked list head D3D11_SHADER_RESOURCE_VIEW_DESC srDesc; srDesc.Format = DXGI_FORMAT_R32_UINT; srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srDesc.Texture2D.MipLevels = 1; srDesc.Texture2D.MostDetailedMip = 0; AMD_V_RETURN(pd3dDevice->CreateShaderResourceView(g_PPLBuffers.pHeadPPLL_Buffer, &srDesc, &g_PPLBuffers.pHeadPPLL_SRV)); // Create UAV view of the buffer containing the heads of the per-pixel linked lists D3D11_UNORDERED_ACCESS_VIEW_DESC UAVHeadPPLLBufferDesc; UAVHeadPPLLBufferDesc.Format = DXGI_FORMAT_R32_UINT; UAVHeadPPLLBufferDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; UAVHeadPPLLBufferDesc.Texture2D.MipSlice = 0; AMD_V_RETURN(pd3dDevice->CreateUnorderedAccessView(g_PPLBuffers.pHeadPPLL_Buffer, &UAVHeadPPLLBufferDesc, &g_PPLBuffers.pHeadPPLL_UAV)); // Per-pixel Linked List (PPLL) buffer D3D11_BUFFER_DESC BufferDesc; BufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; BufferDesc.ByteWidth = (DWORD)(g_HairTotalLayers * winWidth * winHeight * sizeof(PER_PIXEL_LINKED_LIST_STRUCT) ); BufferDesc.CPUAccessFlags = 0; BufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; BufferDesc.Usage = D3D11_USAGE_DEFAULT; BufferDesc.StructureByteStride = sizeof(PER_PIXEL_LINKED_LIST_STRUCT); AMD_V_RETURN(pd3dDevice->CreateBuffer(&BufferDesc, NULL, &g_PPLBuffers.pPPLL_Buffer)); // Create UAV view of Fragment and Link Buffer D3D11_UNORDERED_ACCESS_VIEW_DESC UAVDesc; UAVDesc.Format = DXGI_FORMAT_UNKNOWN; UAVDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; UAVDesc.Buffer.FirstElement = 0; UAVDesc.Buffer.NumElements = (DWORD)(g_HairTotalLayers * winWidth * winHeight); UAVDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_COUNTER; AMD_V_RETURN(pd3dDevice->CreateUnorderedAccessView(g_PPLBuffers.pPPLL_Buffer, &UAVDesc, &g_PPLBuffers.pPPLL_UAV)); // Create SRV view of Fragment and Link Buffer D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; SRVDesc.Format = DXGI_FORMAT_UNKNOWN; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; SRVDesc.Buffer.ElementOffset = 0; SRVDesc.Buffer.ElementWidth = (DWORD)(g_HairTotalLayers * winWidth * winHeight); AMD_V_RETURN(pd3dDevice->CreateShaderResourceView(g_PPLBuffers.pPPLL_Buffer, &SRVDesc, &g_PPLBuffers.pPPLL_SRV)); // update the width and height g_PPLBuffers.width = winWidth; g_PPLBuffers.height = winHeight; // if the refCount is non-zero, then we're just resizing the buffers if (g_PPLBuffers.refCount == 0) { g_PPLBuffers.refCount++; } } else { if (!resize) { g_PPLBuffers.refCount++; } } m_pHeadPPLL_Buffer = g_PPLBuffers.pHeadPPLL_Buffer; m_pHeadPPLL_SRV = g_PPLBuffers.pHeadPPLL_SRV; m_pHeadPPLL_UAV = g_PPLBuffers.pHeadPPLL_UAV; m_pPPLL_Buffer = g_PPLBuffers.pPPLL_Buffer; m_pPPLL_UAV = g_PPLBuffers.pPPLL_UAV; m_pPPLL_SRV = g_PPLBuffers.pPPLL_SRV; return S_OK; }
//-------------------------------------------------------------------------------------- // // OnDestroy // // Called when device is destroyed. // //-------------------------------------------------------------------------------------- void TressFXRenderer::OnDestroy(bool destroyShaders) { m_ShortCut.OnDestroy(destroyShaders); AMD_SAFE_RELEASE(m_pScreenQuadVB); if (destroyShaders) { // vs/ps for rendering hair from the eye camera. AMD_SAFE_RELEASE(m_pVSRenderHair); AMD_SAFE_RELEASE(m_pVSRenderHairAA); AMD_SAFE_RELEASE(m_pVSRenderHairStrandCopies); AMD_SAFE_RELEASE(m_pVSRenderHairAAStrandCopies); // vs to generate hair SM from the light camera. AMD_SAFE_RELEASE(m_pVSGenerateHairSM); // A-buffer AMD_SAFE_RELEASE(m_pPSABuffer_Hair); // PS composite nearest k hair fragments AMD_SAFE_RELEASE(m_pPSKBuffer_Hair); AMD_SAFE_RELEASE(m_pVSScreenQuad); // vertex layouts for hair AMD_SAFE_RELEASE( m_pLayoutHair ); AMD_SAFE_RELEASE( m_pLayoutQuad ); } // constant buffer AMD_SAFE_RELEASE(m_pcbPerFrame); // PPLL buffers DeletePPLL(); // textures and views AMD_SAFE_RELEASE(m_pNoiseTexture2D); AMD_SAFE_RELEASE(m_pNoiseSRV); // Hair shadow map depth stencil buffer AMD_SAFE_RELEASE(m_pSMHairTx); AMD_SAFE_RELEASE(m_pSMHairDSV); AMD_SAFE_RELEASE(m_pSMHairSRV); // render states AMD_SAFE_RELEASE(m_pBlendStateBlendToBg); AMD_SAFE_RELEASE(m_pColorWritesOff ); AMD_SAFE_RELEASE( m_pDepthTestEnabledDSS ); AMD_SAFE_RELEASE( m_pDepthTestEnabledNoDepthWritesStencilWriteIncrementDSS ); AMD_SAFE_RELEASE( m_pDepthTestDisabledStencilTestLessDSS ); AMD_SAFE_RELEASE(m_pSamplerStateLinearWrap ); AMD_SAFE_RELEASE(m_pSamplerStatePointClamp ); AMD_SAFE_RELEASE(m_pSamplerStateCmpLess); }
void GPUOnlyStructuredBuffer::Destroy() { AMD_SAFE_RELEASE(m_pSRV); AMD_SAFE_RELEASE(m_pUAV); AMD_SAFE_RELEASE(m_pBuffer); }
void TressFXShortCut::OnDestroy(bool destroyShaders) { AMD_SAFE_RELEASE(m_pDepthTestEnabled_DSS); AMD_SAFE_RELEASE(m_pDepthTestEnabledNoDepthWritesStencilWriteIncrement_DSS); AMD_SAFE_RELEASE(m_pDepthTestDisabledStencilTestLess_DSS); AMD_SAFE_RELEASE(m_pDepthWriteEnabledStencilTestLess_DSS); AMD_SAFE_RELEASE(m_pDepthWritesToColor_BS); AMD_SAFE_RELEASE(m_pNoWrites_BS); AMD_SAFE_RELEASE(m_pResolveColor_BS); AMD_SAFE_RELEASE(m_pSum_BS); DestroyScreenSizedItems(); if (destroyShaders) { // vs/ps for rendering hair from the eye camera. AMD_SAFE_RELEASE(m_pPSDepthsAlpha); AMD_SAFE_RELEASE(m_pPSResolveDepth); AMD_SAFE_RELEASE(m_pPSFillColors); AMD_SAFE_RELEASE(m_PSResolveColor); } }